[REF][WIP]Yaltik DSL : attempt to migrate to Coconut
This commit is contained in:
parent
407b0fb78f
commit
1202e3c6d4
733
yaltik_dsl/__coconut__.py
Normal file
733
yaltik_dsl/__coconut__.py
Normal file
@ -0,0 +1,733 @@
|
|||||||
|
#!/usr/bin/env python2
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# type: ignore
|
||||||
|
|
||||||
|
# Compiled with Coconut version 1.4.3 [Ernest Scribbler]
|
||||||
|
|
||||||
|
"""Built-in Coconut utilities."""
|
||||||
|
|
||||||
|
# Coconut Header: -------------------------------------------------------------
|
||||||
|
|
||||||
|
from __future__ import print_function, absolute_import, unicode_literals, division
|
||||||
|
import sys as _coconut_sys
|
||||||
|
from __builtin__ import chr, filter, hex, input, int, map, object, oct, open, print, range, str, zip, filter, reversed, enumerate, raw_input, xrange
|
||||||
|
py_chr, py_hex, py_input, py_int, py_map, py_object, py_oct, py_open, py_print, py_range, py_str, py_zip, py_filter, py_reversed, py_enumerate, py_raw_input, py_xrange, py_repr = chr, hex, input, int, map, object, oct, open, print, range, str, zip, filter, reversed, enumerate, raw_input, xrange, repr
|
||||||
|
_coconut_NotImplemented, _coconut_raw_input, _coconut_xrange, _coconut_int, _coconut_long, _coconut_print, _coconut_str, _coconut_unicode, _coconut_repr = NotImplemented, raw_input, xrange, int, long, print, str, unicode, repr
|
||||||
|
from future_builtins import *
|
||||||
|
chr, str = unichr, unicode
|
||||||
|
from io import open
|
||||||
|
class object(object):
|
||||||
|
__slots__ = ()
|
||||||
|
def __ne__(self, other):
|
||||||
|
eq = self == other
|
||||||
|
if eq is _coconut_NotImplemented:
|
||||||
|
return eq
|
||||||
|
return not eq
|
||||||
|
class int(_coconut_int):
|
||||||
|
__slots__ = ()
|
||||||
|
if hasattr(_coconut_int, "__doc__"):
|
||||||
|
__doc__ = _coconut_int.__doc__
|
||||||
|
class __metaclass__(type):
|
||||||
|
def __instancecheck__(cls, inst):
|
||||||
|
return _coconut.isinstance(inst, (_coconut_int, _coconut_long))
|
||||||
|
def __subclasscheck__(cls, subcls):
|
||||||
|
return _coconut.issubclass(subcls, (_coconut_int, _coconut_long))
|
||||||
|
class range(object):
|
||||||
|
__slots__ = ("_xrange",)
|
||||||
|
if hasattr(_coconut_xrange, "__doc__"):
|
||||||
|
__doc__ = _coconut_xrange.__doc__
|
||||||
|
def __init__(self, *args):
|
||||||
|
self._xrange = _coconut_xrange(*args)
|
||||||
|
def __iter__(self):
|
||||||
|
return _coconut.iter(self._xrange)
|
||||||
|
def __reversed__(self):
|
||||||
|
return _coconut.reversed(self._xrange)
|
||||||
|
def __len__(self):
|
||||||
|
return _coconut.len(self._xrange)
|
||||||
|
def __contains__(self, elem):
|
||||||
|
return elem in self._xrange
|
||||||
|
def __getitem__(self, index):
|
||||||
|
if _coconut.isinstance(index, _coconut.slice):
|
||||||
|
args = _coconut.slice(*self._args)
|
||||||
|
start, stop, step, ind_step = (args.start if args.start is not None else 0), args.stop, (args.step if args.step is not None else 1), (index.step if index.step is not None else 1)
|
||||||
|
return self.__class__((start if ind_step >= 0 else stop - step) if index.start is None else start + step * index.start if index.start >= 0 else stop + step * index.start, (stop if ind_step >= 0 else start - step) if index.stop is None else start + step * index.stop if index.stop >= 0 else stop + step * index.stop, step if index.step is None else step * index.step)
|
||||||
|
else:
|
||||||
|
return self._xrange[index]
|
||||||
|
def count(self, elem):
|
||||||
|
"""Count the number of times elem appears in the range."""
|
||||||
|
return _coconut_int(elem in self._xrange)
|
||||||
|
def index(self, elem):
|
||||||
|
"""Find the index of elem in the range."""
|
||||||
|
if elem not in self._xrange: raise _coconut.ValueError(_coconut.repr(elem) + " is not in range")
|
||||||
|
start, _, step = self._xrange.__reduce_ex__(2)[1]
|
||||||
|
return (elem - start) // step
|
||||||
|
def __repr__(self):
|
||||||
|
return _coconut.repr(self._xrange)[1:]
|
||||||
|
@property
|
||||||
|
def _args(self):
|
||||||
|
return self._xrange.__reduce__()[1]
|
||||||
|
def __reduce_ex__(self, protocol):
|
||||||
|
return (self.__class__, self._xrange.__reduce_ex__(protocol)[1])
|
||||||
|
def __reduce__(self):
|
||||||
|
return self.__reduce_ex__(_coconut.pickle.DEFAULT_PROTOCOL)
|
||||||
|
def __hash__(self):
|
||||||
|
return _coconut.hash(self._args)
|
||||||
|
def __copy__(self):
|
||||||
|
return self.__class__(*self._args)
|
||||||
|
def __eq__(self, other):
|
||||||
|
return _coconut.isinstance(other, self.__class__) and self._args == other._args
|
||||||
|
from collections import Sequence as _coconut_Sequence
|
||||||
|
_coconut_Sequence.register(range)
|
||||||
|
from functools import wraps as _coconut_wraps
|
||||||
|
@_coconut_wraps(_coconut_print)
|
||||||
|
def print(*args, **kwargs):
|
||||||
|
file = kwargs.get("file", _coconut_sys.stdout)
|
||||||
|
flush = kwargs.get("flush", False)
|
||||||
|
if "flush" in kwargs:
|
||||||
|
del kwargs["flush"]
|
||||||
|
if _coconut.hasattr(file, "encoding") and file.encoding is not None:
|
||||||
|
_coconut_print(*(_coconut_unicode(x).encode(file.encoding) for x in args), **kwargs)
|
||||||
|
else:
|
||||||
|
_coconut_print(*(_coconut_unicode(x).encode() for x in args), **kwargs)
|
||||||
|
if flush:
|
||||||
|
file.flush()
|
||||||
|
@_coconut_wraps(_coconut_raw_input)
|
||||||
|
def input(*args, **kwargs):
|
||||||
|
if _coconut.hasattr(_coconut_sys.stdout, "encoding") and _coconut_sys.stdout.encoding is not None:
|
||||||
|
return _coconut_raw_input(*args, **kwargs).decode(_coconut_sys.stdout.encoding)
|
||||||
|
return _coconut_raw_input(*args, **kwargs).decode()
|
||||||
|
@_coconut_wraps(_coconut_repr)
|
||||||
|
def repr(obj):
|
||||||
|
if isinstance(obj, _coconut_unicode):
|
||||||
|
return _coconut_unicode(_coconut_repr(obj)[1:])
|
||||||
|
if isinstance(obj, _coconut_str):
|
||||||
|
return "b" + _coconut_unicode(_coconut_repr(obj))
|
||||||
|
return _coconut_unicode(_coconut_repr(obj))
|
||||||
|
ascii = repr
|
||||||
|
def raw_input(*args):
|
||||||
|
"""Coconut uses Python 3 "input" instead of Python 2 "raw_input"."""
|
||||||
|
raise _coconut.NameError('Coconut uses Python 3 "input" instead of Python 2 "raw_input"')
|
||||||
|
def xrange(*args):
|
||||||
|
"""Coconut uses Python 3 "range" instead of Python 2 "xrange"."""
|
||||||
|
raise _coconut.NameError('Coconut uses Python 3 "range" instead of Python 2 "xrange"')
|
||||||
|
class _coconut(object):
|
||||||
|
import collections, copy, functools, types, itertools, operator, threading, weakref, os, warnings
|
||||||
|
try:
|
||||||
|
from backports.functools_lru_cache import lru_cache
|
||||||
|
functools.lru_cache = lru_cache
|
||||||
|
except ImportError: pass
|
||||||
|
try:
|
||||||
|
import trollius as asyncio
|
||||||
|
except ImportError:
|
||||||
|
class you_need_to_install_trollius: pass
|
||||||
|
asyncio = you_need_to_install_trollius()
|
||||||
|
import cPickle as pickle
|
||||||
|
OrderedDict = collections.OrderedDict
|
||||||
|
abc = collections
|
||||||
|
class typing(object):
|
||||||
|
@staticmethod
|
||||||
|
def NamedTuple(name, fields):
|
||||||
|
return _coconut.collections.namedtuple(name, [x for x, t in fields])
|
||||||
|
Ellipsis, Exception, AttributeError, ImportError, IndexError, KeyError, NameError, TypeError, ValueError, StopIteration, classmethod, dict, enumerate, filter, float, frozenset, getattr, hasattr, hash, id, int, isinstance, issubclass, iter, len, list, locals, map, min, max, next, object, property, range, reversed, set, slice, str, sum, super, tuple, type, zip, repr, bytearray = Ellipsis, Exception, AttributeError, ImportError, IndexError, KeyError, NameError, TypeError, ValueError, StopIteration, classmethod, dict, enumerate, filter, float, frozenset, getattr, hasattr, hash, id, int, isinstance, issubclass, iter, len, list, locals, map, min, max, next, object, property, range, reversed, set, slice, str, sum, super, tuple, type, zip, staticmethod(repr), bytearray
|
||||||
|
_coconut_sentinel = _coconut.object()
|
||||||
|
class MatchError(Exception):
|
||||||
|
"""Pattern-matching error. Has attributes .pattern and .value."""
|
||||||
|
__slots__ = ("pattern", "value")
|
||||||
|
def _coconut_igetitem(iterable, index):
|
||||||
|
if isinstance(iterable, (_coconut_reversed, _coconut_map, _coconut.zip, _coconut_enumerate, _coconut_count, _coconut.abc.Sequence)):
|
||||||
|
return iterable[index]
|
||||||
|
if not _coconut.isinstance(index, _coconut.slice):
|
||||||
|
if index < 0:
|
||||||
|
return _coconut.collections.deque(iterable, maxlen=-index)[0]
|
||||||
|
return _coconut.next(_coconut.itertools.islice(iterable, index, index + 1))
|
||||||
|
if index.start is not None and index.start < 0 and (index.stop is None or index.stop < 0) and index.step is None:
|
||||||
|
queue = _coconut.collections.deque(iterable, maxlen=-index.start)
|
||||||
|
if index.stop is not None:
|
||||||
|
queue = _coconut.list(queue)[:index.stop - index.start]
|
||||||
|
return queue
|
||||||
|
if (index.start is not None and index.start < 0) or (index.stop is not None and index.stop < 0) or (index.step is not None and index.step < 0):
|
||||||
|
return _coconut.list(iterable)[index]
|
||||||
|
return _coconut.itertools.islice(iterable, index.start, index.stop, index.step)
|
||||||
|
class _coconut_base_compose(object):
|
||||||
|
__slots__ = ("func", "funcstars")
|
||||||
|
def __init__(self, func, *funcstars):
|
||||||
|
self.func = func
|
||||||
|
self.funcstars = []
|
||||||
|
for f, stars in funcstars:
|
||||||
|
if _coconut.isinstance(f, _coconut_base_compose):
|
||||||
|
self.funcstars.append((f.func, stars))
|
||||||
|
self.funcstars += f.funcstars
|
||||||
|
else:
|
||||||
|
self.funcstars.append((f, stars))
|
||||||
|
def __call__(self, *args, **kwargs):
|
||||||
|
arg = self.func(*args, **kwargs)
|
||||||
|
for f, stars in self.funcstars:
|
||||||
|
if stars == 0:
|
||||||
|
arg = f(arg)
|
||||||
|
elif stars == 1:
|
||||||
|
arg = f(*arg)
|
||||||
|
elif stars == 2:
|
||||||
|
arg = f(**arg)
|
||||||
|
else:
|
||||||
|
raise _coconut.ValueError("invalid arguments to " + _coconut.repr(self))
|
||||||
|
return arg
|
||||||
|
def __repr__(self):
|
||||||
|
return _coconut.repr(self.func) + " " + " ".join(("..*> " if star == 1 else "..**>" if star == 2 else "..> ") + _coconut.repr(f) for f, star in self.funcstars)
|
||||||
|
def __reduce__(self):
|
||||||
|
return (self.__class__, (self.func,) + _coconut.tuple(self.funcstars))
|
||||||
|
def __get__(self, obj, objtype=None):
|
||||||
|
return _coconut.functools.partial(self, obj)
|
||||||
|
def _coconut_forward_compose(func, *funcs): return _coconut_base_compose(func, *((f, 0) for f in funcs))
|
||||||
|
def _coconut_back_compose(*funcs): return _coconut_forward_compose(*_coconut.reversed(funcs))
|
||||||
|
def _coconut_forward_star_compose(func, *funcs): return _coconut_base_compose(func, *((f, 1) for f in funcs))
|
||||||
|
def _coconut_back_star_compose(*funcs): return _coconut_forward_star_compose(*_coconut.reversed(funcs))
|
||||||
|
def _coconut_forward_dubstar_compose(func, *funcs): return _coconut_base_compose(func, *((f, 2) for f in funcs))
|
||||||
|
def _coconut_back_dubstar_compose(*funcs): return _coconut_forward_dubstar_compose(*_coconut.reversed(funcs))
|
||||||
|
def _coconut_pipe(x, f): return f(x)
|
||||||
|
def _coconut_star_pipe(xs, f): return f(*xs)
|
||||||
|
def _coconut_dubstar_pipe(kws, f): return f(**kws)
|
||||||
|
def _coconut_back_pipe(f, x): return f(x)
|
||||||
|
def _coconut_back_star_pipe(f, xs): return f(*xs)
|
||||||
|
def _coconut_back_dubstar_pipe(f, kws): return f(**kws)
|
||||||
|
def _coconut_assert(cond, msg=None): assert cond, msg if msg is not None else "(assert) got falsey value " + _coconut.repr(cond)
|
||||||
|
def _coconut_bool_and(a, b): return a and b
|
||||||
|
def _coconut_bool_or(a, b): return a or b
|
||||||
|
def _coconut_none_coalesce(a, b): return a if a is not None else b
|
||||||
|
def _coconut_minus(a, *rest):
|
||||||
|
if not rest:
|
||||||
|
return -a
|
||||||
|
for b in rest:
|
||||||
|
a = a - b
|
||||||
|
return a
|
||||||
|
@_coconut.functools.wraps(_coconut.itertools.tee)
|
||||||
|
def tee(iterable, n=2):
|
||||||
|
if n >= 0 and _coconut.isinstance(iterable, (_coconut.tuple, _coconut.frozenset)):
|
||||||
|
return (iterable,) * n
|
||||||
|
if n > 0 and (_coconut.hasattr(iterable, "__copy__") or _coconut.isinstance(iterable, _coconut.abc.Sequence)):
|
||||||
|
return (iterable,) + _coconut.tuple(_coconut.copy.copy(iterable) for _ in _coconut.range(n - 1))
|
||||||
|
return _coconut.itertools.tee(iterable, n)
|
||||||
|
class reiterable(object):
|
||||||
|
"""Allows an iterator to be iterated over multiple times."""
|
||||||
|
__slots__ = ("iter",)
|
||||||
|
def __init__(self, iterable):
|
||||||
|
self.iter = iterable
|
||||||
|
def _get_new_iter(self):
|
||||||
|
self.iter, new_iter = _coconut_tee(self.iter)
|
||||||
|
return new_iter
|
||||||
|
def __iter__(self):
|
||||||
|
return _coconut.iter(self._get_new_iter())
|
||||||
|
def __getitem__(self, index):
|
||||||
|
return _coconut_igetitem(self._get_new_iter(), index)
|
||||||
|
def __reversed__(self):
|
||||||
|
return _coconut_reversed(self._get_new_iter())
|
||||||
|
def __len__(self):
|
||||||
|
return _coconut.len(self.iter)
|
||||||
|
def __repr__(self):
|
||||||
|
return "reiterable(%r)" % (self.iter,)
|
||||||
|
def __reduce__(self):
|
||||||
|
return (self.__class__, (self.iter,))
|
||||||
|
def __copy__(self):
|
||||||
|
return self.__class__(self._get_new_iter())
|
||||||
|
def __fmap__(self, func):
|
||||||
|
return _coconut_map(func, self)
|
||||||
|
class scan(object):
|
||||||
|
"""Reduce func over iterable, yielding intermediate results,
|
||||||
|
optionally starting from initializer."""
|
||||||
|
__slots__ = ("func", "iter", "initializer")
|
||||||
|
def __init__(self, function, iterable, initializer=_coconut_sentinel):
|
||||||
|
self.func = function
|
||||||
|
self.iter = iterable
|
||||||
|
self.initializer = initializer
|
||||||
|
def __iter__(self):
|
||||||
|
acc = self.initializer
|
||||||
|
if acc is not _coconut_sentinel:
|
||||||
|
yield acc
|
||||||
|
for item in self.iter:
|
||||||
|
if acc is _coconut_sentinel:
|
||||||
|
acc = item
|
||||||
|
else:
|
||||||
|
acc = self.func(acc, item)
|
||||||
|
yield acc
|
||||||
|
def __len__(self):
|
||||||
|
return _coconut.len(self.iter)
|
||||||
|
def __repr__(self):
|
||||||
|
return "scan(%r, %r)" % (self.func, self.iter)
|
||||||
|
def __reduce__(self):
|
||||||
|
return (self.__class__, (self.func, self.iter))
|
||||||
|
def __copy__(self):
|
||||||
|
return self.__class__(self.func, _coconut.copy.copy(self.iter))
|
||||||
|
def __fmap__(self, func):
|
||||||
|
return _coconut_map(func, self)
|
||||||
|
class reversed(object):
|
||||||
|
__slots__ = ("iter",)
|
||||||
|
if hasattr(_coconut.map, "__doc__"):
|
||||||
|
__doc__ = _coconut.reversed.__doc__
|
||||||
|
def __new__(cls, iterable):
|
||||||
|
if _coconut.isinstance(iterable, _coconut.range):
|
||||||
|
return iterable[::-1]
|
||||||
|
if not _coconut.hasattr(iterable, "__reversed__") or _coconut.isinstance(iterable, (_coconut.list, _coconut.tuple)):
|
||||||
|
return _coconut.object.__new__(cls)
|
||||||
|
return _coconut.reversed(iterable)
|
||||||
|
def __init__(self, iterable):
|
||||||
|
self.iter = iterable
|
||||||
|
def __iter__(self):
|
||||||
|
return _coconut.iter(_coconut.reversed(self.iter))
|
||||||
|
def __getitem__(self, index):
|
||||||
|
if _coconut.isinstance(index, _coconut.slice):
|
||||||
|
return _coconut_igetitem(self.iter, _coconut.slice(-(index.start + 1) if index.start is not None else None, -(index.stop + 1) if index.stop else None, -(index.step if index.step is not None else 1)))
|
||||||
|
return _coconut_igetitem(self.iter, -(index + 1))
|
||||||
|
def __reversed__(self):
|
||||||
|
return self.iter
|
||||||
|
def __len__(self):
|
||||||
|
return _coconut.len(self.iter)
|
||||||
|
def __repr__(self):
|
||||||
|
return "reversed(%r)" % (self.iter,)
|
||||||
|
def __hash__(self):
|
||||||
|
return -_coconut.hash(self.iter)
|
||||||
|
def __reduce__(self):
|
||||||
|
return (self.__class__, (self.iter,))
|
||||||
|
def __copy__(self):
|
||||||
|
return self.__class__(_coconut.copy.copy(self.iter))
|
||||||
|
def __eq__(self, other):
|
||||||
|
return isinstance(other, self.__class__) and self.iter == other.iter
|
||||||
|
def __contains__(self, elem):
|
||||||
|
return elem in self.iter
|
||||||
|
def count(self, elem):
|
||||||
|
"""Count the number of times elem appears in the reversed iterator."""
|
||||||
|
return self.iter.count(elem)
|
||||||
|
def index(self, elem):
|
||||||
|
"""Find the index of elem in the reversed iterator."""
|
||||||
|
return _coconut.len(self.iter) - self.iter.index(elem) - 1
|
||||||
|
def __fmap__(self, func):
|
||||||
|
return self.__class__(_coconut_map(func, self.iter))
|
||||||
|
class map(_coconut.map):
|
||||||
|
__slots__ = ("func", "iters")
|
||||||
|
if hasattr(_coconut.map, "__doc__"):
|
||||||
|
__doc__ = _coconut.map.__doc__
|
||||||
|
def __new__(cls, function, *iterables):
|
||||||
|
new_map = _coconut.map.__new__(cls, function, *iterables)
|
||||||
|
new_map.func = function
|
||||||
|
new_map.iters = iterables
|
||||||
|
return new_map
|
||||||
|
def __getitem__(self, index):
|
||||||
|
if _coconut.isinstance(index, _coconut.slice):
|
||||||
|
return self.__class__(self.func, *(_coconut_igetitem(i, index) for i in self.iters))
|
||||||
|
return self.func(*(_coconut_igetitem(i, index) for i in self.iters))
|
||||||
|
def __reversed__(self):
|
||||||
|
return self.__class__(self.func, *(_coconut_reversed(i) for i in self.iters))
|
||||||
|
def __len__(self):
|
||||||
|
return _coconut.min(_coconut.len(i) for i in self.iters)
|
||||||
|
def __repr__(self):
|
||||||
|
return "map(%r, %s)" % (self.func, ", ".join((_coconut.repr(i) for i in self.iters)))
|
||||||
|
def __reduce__(self):
|
||||||
|
return (self.__class__, (self.func,) + self.iters)
|
||||||
|
def __reduce_ex__(self, _):
|
||||||
|
return self.__reduce__()
|
||||||
|
def __copy__(self):
|
||||||
|
return self.__class__(self.func, *_coconut.map(_coconut.copy.copy, self.iters))
|
||||||
|
def __fmap__(self, func):
|
||||||
|
return self.__class__(_coconut_forward_compose(self.func, func), *self.iters)
|
||||||
|
class parallel_map(map):
|
||||||
|
"""Multi-process implementation of map using concurrent.futures.
|
||||||
|
Requires arguments to be pickleable."""
|
||||||
|
__slots__ = ()
|
||||||
|
def __iter__(self):
|
||||||
|
from concurrent.futures import ProcessPoolExecutor
|
||||||
|
with ProcessPoolExecutor() as executor:
|
||||||
|
return _coconut.iter(_coconut.list(executor.map(self.func, *self.iters)))
|
||||||
|
def __repr__(self):
|
||||||
|
return "parallel_" + _coconut_map.__repr__(self)
|
||||||
|
class concurrent_map(map):
|
||||||
|
"""Multi-thread implementation of map using concurrent.futures."""
|
||||||
|
__slots__ = ()
|
||||||
|
def __iter__(self):
|
||||||
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
|
from multiprocessing import cpu_count # cpu_count() * 5 is the default Python 3.5 thread count
|
||||||
|
with ThreadPoolExecutor(cpu_count() * 5) as executor:
|
||||||
|
return _coconut.iter(_coconut.list(executor.map(self.func, *self.iters)))
|
||||||
|
def __repr__(self):
|
||||||
|
return "concurrent_" + _coconut_map.__repr__(self)
|
||||||
|
class filter(_coconut.filter):
|
||||||
|
__slots__ = ("func", "iter")
|
||||||
|
if hasattr(_coconut.filter, "__doc__"):
|
||||||
|
__doc__ = _coconut.filter.__doc__
|
||||||
|
def __new__(cls, function, iterable):
|
||||||
|
new_filter = _coconut.filter.__new__(cls, function, iterable)
|
||||||
|
new_filter.func = function
|
||||||
|
new_filter.iter = iterable
|
||||||
|
return new_filter
|
||||||
|
def __reversed__(self):
|
||||||
|
return self.__class__(self.func, _coconut_reversed(self.iter))
|
||||||
|
def __repr__(self):
|
||||||
|
return "filter(%r, %r)" % (self.func, self.iter)
|
||||||
|
def __reduce__(self):
|
||||||
|
return (self.__class__, (self.func, self.iter))
|
||||||
|
def __reduce_ex__(self, _):
|
||||||
|
return self.__reduce__()
|
||||||
|
def __copy__(self):
|
||||||
|
return self.__class__(self.func, _coconut.copy.copy(self.iter))
|
||||||
|
def __fmap__(self, func):
|
||||||
|
return _coconut_map(func, self)
|
||||||
|
class zip(_coconut.zip):
|
||||||
|
__slots__ = ("iters",)
|
||||||
|
if hasattr(_coconut.zip, "__doc__"):
|
||||||
|
__doc__ = _coconut.zip.__doc__
|
||||||
|
def __new__(cls, *iterables):
|
||||||
|
new_zip = _coconut.zip.__new__(cls, *iterables)
|
||||||
|
new_zip.iters = iterables
|
||||||
|
return new_zip
|
||||||
|
def __getitem__(self, index):
|
||||||
|
if _coconut.isinstance(index, _coconut.slice):
|
||||||
|
return self.__class__(*(_coconut_igetitem(i, index) for i in self.iters))
|
||||||
|
return _coconut.tuple(_coconut_igetitem(i, index) for i in self.iters)
|
||||||
|
def __reversed__(self):
|
||||||
|
return self.__class__(*(_coconut_reversed(i) for i in self.iters))
|
||||||
|
def __len__(self):
|
||||||
|
return _coconut.min(_coconut.len(i) for i in self.iters)
|
||||||
|
def __repr__(self):
|
||||||
|
return "zip(%s)" % (", ".join((_coconut.repr(i) for i in self.iters)),)
|
||||||
|
def __reduce__(self):
|
||||||
|
return (self.__class__, self.iters)
|
||||||
|
def __reduce_ex__(self, _):
|
||||||
|
return self.__reduce__()
|
||||||
|
def __copy__(self):
|
||||||
|
return self.__class__(*_coconut.map(_coconut.copy.copy, self.iters))
|
||||||
|
def __fmap__(self, func):
|
||||||
|
return _coconut_map(func, self)
|
||||||
|
class enumerate(_coconut.enumerate):
|
||||||
|
__slots__ = ("iter", "start")
|
||||||
|
if hasattr(_coconut.enumerate, "__doc__"):
|
||||||
|
__doc__ = _coconut.enumerate.__doc__
|
||||||
|
def __new__(cls, iterable, start=0):
|
||||||
|
new_enumerate = _coconut.enumerate.__new__(cls, iterable, start)
|
||||||
|
new_enumerate.iter = iterable
|
||||||
|
new_enumerate.start = start
|
||||||
|
return new_enumerate
|
||||||
|
def __getitem__(self, index):
|
||||||
|
if _coconut.isinstance(index, _coconut.slice):
|
||||||
|
return self.__class__(_coconut_igetitem(self.iter, index), self.start + (0 if index.start is None else index.start if index.start >= 0 else len(self.iter) + index.start))
|
||||||
|
return (self.start + index, _coconut_igetitem(self.iter, index))
|
||||||
|
def __len__(self):
|
||||||
|
return _coconut.len(self.iter)
|
||||||
|
def __repr__(self):
|
||||||
|
return "enumerate(%r, %r)" % (self.iter, self.start)
|
||||||
|
def __reduce__(self):
|
||||||
|
return (self.__class__, (self.iter, self.start))
|
||||||
|
def __reduce_ex__(self, _):
|
||||||
|
return self.__reduce__()
|
||||||
|
def __copy__(self):
|
||||||
|
return self.__class__(_coconut.copy.copy(self.iter), self.start)
|
||||||
|
def __fmap__(self, func):
|
||||||
|
return _coconut_map(func, self)
|
||||||
|
class count(object):
|
||||||
|
"""count(start, step) returns an infinite iterator starting at start and increasing by step.
|
||||||
|
If step is set to 0, count will infinitely repeat its first argument."""
|
||||||
|
__slots__ = ("start", "step")
|
||||||
|
def __init__(self, start=0, step=1):
|
||||||
|
self.start = start
|
||||||
|
self.step = step
|
||||||
|
def __iter__(self):
|
||||||
|
while True:
|
||||||
|
yield self.start
|
||||||
|
if self.step:
|
||||||
|
self.start += self.step
|
||||||
|
def __contains__(self, elem):
|
||||||
|
if not self.step:
|
||||||
|
return elem == self.start
|
||||||
|
if elem < self.start:
|
||||||
|
return False
|
||||||
|
return (elem - self.start) % self.step == 0
|
||||||
|
def __getitem__(self, index):
|
||||||
|
if _coconut.isinstance(index, _coconut.slice) and (index.start is None or index.start >= 0) and (index.stop is None or index.stop >= 0):
|
||||||
|
new_start, new_step = self.start, self.step
|
||||||
|
if self.step and index.start is not None:
|
||||||
|
new_start += self.step * index.start
|
||||||
|
if self.step and index.step is not None:
|
||||||
|
new_step *= index.step
|
||||||
|
if index.stop is None:
|
||||||
|
return self.__class__(new_start, new_step)
|
||||||
|
if self.step and _coconut.isinstance(self.start, _coconut.int) and _coconut.isinstance(self.step, _coconut.int):
|
||||||
|
return _coconut.range(new_start, self.start + self.step * index.stop, new_step)
|
||||||
|
return _coconut_map(self.__getitem__, _coconut.range(index.start if index.start is not None else 0, index.stop, index.step if index.step is not None else 1))
|
||||||
|
if index < 0:
|
||||||
|
raise _coconut.IndexError("count indices must be positive")
|
||||||
|
return self.start + self.step * index if self.step else self.start
|
||||||
|
def count(self, elem):
|
||||||
|
"""Count the number of times elem appears in the count."""
|
||||||
|
if not self.step:
|
||||||
|
return _coconut.float("inf") if elem == self.start else 0
|
||||||
|
return int(elem in self)
|
||||||
|
def index(self, elem):
|
||||||
|
"""Find the index of elem in the count."""
|
||||||
|
if elem not in self:
|
||||||
|
raise _coconut.ValueError(_coconut.repr(elem) + " not in " + _coconut.repr(self))
|
||||||
|
return (elem - self.start) // self.step if self.step else 0
|
||||||
|
def __reversed__(self):
|
||||||
|
if not self.step:
|
||||||
|
return self
|
||||||
|
raise _coconut.TypeError(repr(self) + " object is not reversible")
|
||||||
|
def __repr__(self):
|
||||||
|
return "count(%r, %r)" % (self.start, self.step)
|
||||||
|
def __hash__(self):
|
||||||
|
return _coconut.hash((self.start, self.step))
|
||||||
|
def __reduce__(self):
|
||||||
|
return (self.__class__, (self.start, self.step))
|
||||||
|
def __copy__(self):
|
||||||
|
return self.__class__(self.start, self.step)
|
||||||
|
def __eq__(self, other):
|
||||||
|
return isinstance(other, self.__class__) and self.start == other.start and self.step == other.step
|
||||||
|
def __fmap__(self, func):
|
||||||
|
return _coconut_map(func, self)
|
||||||
|
class groupsof(object):
|
||||||
|
"""groupsof(n, iterable) splits iterable into groups of size n.
|
||||||
|
If the length of the iterable is not divisible by n, the last group may be of size < n."""
|
||||||
|
__slots__ = ("group_size", "iter")
|
||||||
|
def __init__(self, n, iterable):
|
||||||
|
self.iter = iterable
|
||||||
|
try:
|
||||||
|
self.group_size = _coconut.int(n)
|
||||||
|
except _coconut.ValueError:
|
||||||
|
raise _coconut.TypeError("group size must be an int; not %r" % (n,))
|
||||||
|
if self.group_size <= 0:
|
||||||
|
raise _coconut.ValueError("group size must be > 0; not %r" % (self.group_size,))
|
||||||
|
def __iter__(self):
|
||||||
|
iterator = _coconut.iter(self.iter)
|
||||||
|
loop = True
|
||||||
|
while loop:
|
||||||
|
group = []
|
||||||
|
for _ in _coconut.range(self.group_size):
|
||||||
|
try:
|
||||||
|
group.append(_coconut.next(iterator))
|
||||||
|
except _coconut.StopIteration:
|
||||||
|
loop = False
|
||||||
|
break
|
||||||
|
if group:
|
||||||
|
yield _coconut.tuple(group)
|
||||||
|
def __len__(self):
|
||||||
|
return _coconut.len(self.iter)
|
||||||
|
def __repr__(self):
|
||||||
|
return "groupsof(%r)" % (self.iter,)
|
||||||
|
def __reduce__(self):
|
||||||
|
return (self.__class__, (self.group_size, self.iter))
|
||||||
|
def __copy__(self):
|
||||||
|
return self.__class__(self.group_size, _coconut.copy.copy(self.iter))
|
||||||
|
def __fmap__(self, func):
|
||||||
|
return _coconut_map(func, self)
|
||||||
|
class recursive_iterator(object):
|
||||||
|
"""Decorator that optimizes a function for iterator recursion."""
|
||||||
|
__slots__ = ("func", "tee_store", "backup_tee_store")
|
||||||
|
def __init__(self, func):
|
||||||
|
self.func = func
|
||||||
|
self.tee_store = {}
|
||||||
|
self.backup_tee_store = []
|
||||||
|
def __call__(self, *args, **kwargs):
|
||||||
|
key = (args, _coconut.frozenset(kwargs))
|
||||||
|
use_backup = False
|
||||||
|
try:
|
||||||
|
hash(key)
|
||||||
|
except _coconut.Exception:
|
||||||
|
try:
|
||||||
|
key = _coconut.pickle.dumps(key, -1)
|
||||||
|
except _coconut.Exception:
|
||||||
|
use_backup = True
|
||||||
|
if use_backup:
|
||||||
|
for i, (k, v) in _coconut.enumerate(self.backup_tee_store):
|
||||||
|
if k == key:
|
||||||
|
to_tee, store_pos = v, i
|
||||||
|
break
|
||||||
|
else: # no break
|
||||||
|
to_tee = self.func(*args, **kwargs)
|
||||||
|
store_pos = None
|
||||||
|
to_store, to_return = _coconut_tee(to_tee)
|
||||||
|
if store_pos is None:
|
||||||
|
self.backup_tee_store.append([key, to_store])
|
||||||
|
else:
|
||||||
|
self.backup_tee_store[store_pos][1] = to_store
|
||||||
|
else:
|
||||||
|
self.tee_store[key], to_return = _coconut_tee(self.tee_store.get(key) or self.func(*args, **kwargs))
|
||||||
|
return to_return
|
||||||
|
def __repr__(self):
|
||||||
|
return "@recursive_iterator(" + _coconut.repr(self.func) + ")"
|
||||||
|
def __reduce__(self):
|
||||||
|
return (self.__class__, (self.func,))
|
||||||
|
def __get__(self, obj, objtype=None):
|
||||||
|
return _coconut.functools.partial(self, obj)
|
||||||
|
class _coconut_FunctionMatchErrorContext(object):
|
||||||
|
__slots__ = ('exc_class', 'taken')
|
||||||
|
threadlocal_var = _coconut.threading.local()
|
||||||
|
def __init__(self, exc_class):
|
||||||
|
self.exc_class = exc_class
|
||||||
|
self.taken = False
|
||||||
|
def __enter__(self):
|
||||||
|
try:
|
||||||
|
self.threadlocal_var.contexts.append(self)
|
||||||
|
except _coconut.AttributeError:
|
||||||
|
self.threadlocal_var.contexts = [self]
|
||||||
|
def __exit__(self, type, value, traceback):
|
||||||
|
self.threadlocal_var.contexts.pop()
|
||||||
|
@classmethod
|
||||||
|
def get(cls):
|
||||||
|
try:
|
||||||
|
ctx = cls.threadlocal_var.contexts[-1]
|
||||||
|
except (_coconut.AttributeError, _coconut.IndexError):
|
||||||
|
return _coconut_MatchError
|
||||||
|
if not ctx.taken:
|
||||||
|
ctx.taken = True
|
||||||
|
return ctx.exc_class
|
||||||
|
return _coconut_MatchError
|
||||||
|
_coconut_get_function_match_error = _coconut_FunctionMatchErrorContext.get
|
||||||
|
class _coconut_base_pattern_func(object):
|
||||||
|
__slots__ = ("FunctionMatchError", "__doc__", "patterns")
|
||||||
|
_coconut_is_match = True
|
||||||
|
def __init__(self, *funcs):
|
||||||
|
self.FunctionMatchError = _coconut.type(_coconut_str("MatchError"), (_coconut_MatchError,), {})
|
||||||
|
self.__doc__ = None
|
||||||
|
self.patterns = []
|
||||||
|
for func in funcs:
|
||||||
|
self.add(func)
|
||||||
|
def add(self, func):
|
||||||
|
self.__doc__ = _coconut.getattr(func, "__doc__", None) or self.__doc__
|
||||||
|
if _coconut.isinstance(func, _coconut_base_pattern_func):
|
||||||
|
self.patterns += func.patterns
|
||||||
|
else:
|
||||||
|
self.patterns.append(func)
|
||||||
|
def __call__(self, *args, **kwargs):
|
||||||
|
for func in self.patterns[:-1]:
|
||||||
|
try:
|
||||||
|
with _coconut_FunctionMatchErrorContext(self.FunctionMatchError):
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
except self.FunctionMatchError:
|
||||||
|
pass
|
||||||
|
return self.patterns[-1](*args, **kwargs)
|
||||||
|
def _coconut_tco_func(self, *args, **kwargs):
|
||||||
|
for func in self.patterns[:-1]:
|
||||||
|
try:
|
||||||
|
with _coconut_FunctionMatchErrorContext(self.FunctionMatchError):
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
except self.FunctionMatchError:
|
||||||
|
pass
|
||||||
|
return _coconut_tail_call(self.patterns[-1], *args, **kwargs)
|
||||||
|
def __repr__(self):
|
||||||
|
return "addpattern(" + _coconut.repr(self.patterns[0]) + ")(*" + _coconut.repr(self.patterns[1:]) + ")"
|
||||||
|
def __reduce__(self):
|
||||||
|
return (self.__class__, _coconut.tuple(self.patterns))
|
||||||
|
def __get__(self, obj, objtype=None):
|
||||||
|
if obj is None:
|
||||||
|
return self
|
||||||
|
return _coconut.functools.partial(self, obj)
|
||||||
|
def _coconut_mark_as_match(base_func):
|
||||||
|
base_func._coconut_is_match = True
|
||||||
|
return base_func
|
||||||
|
def addpattern(base_func, **kwargs):
|
||||||
|
"""Decorator to add a new case to a pattern-matching function,
|
||||||
|
where the new case is checked last."""
|
||||||
|
allow_any_func = kwargs.pop("allow_any_func", False)
|
||||||
|
if not allow_any_func and not _coconut.getattr(base_func, "_coconut_is_match", False):
|
||||||
|
_coconut.warnings.warn("Possible misuse of addpattern with non-pattern-matching function " + _coconut.repr(base_func) + " (pass allow_any_func=True to dismiss)", stacklevel=2)
|
||||||
|
if kwargs:
|
||||||
|
raise _coconut.TypeError("addpattern() got unexpected keyword arguments " + _coconut.repr(kwargs))
|
||||||
|
return _coconut.functools.partial(_coconut_base_pattern_func, base_func)
|
||||||
|
_coconut_addpattern = addpattern
|
||||||
|
def prepattern(base_func, **kwargs):
|
||||||
|
"""DEPRECATED: Use addpattern instead."""
|
||||||
|
def pattern_prepender(func):
|
||||||
|
return addpattern(func, **kwargs)(base_func)
|
||||||
|
return pattern_prepender
|
||||||
|
class _coconut_partial(object):
|
||||||
|
__slots__ = ("func", "_argdict", "_arglen", "_stargs", "keywords")
|
||||||
|
if hasattr(_coconut.functools.partial, "__doc__"):
|
||||||
|
__doc__ = _coconut.functools.partial.__doc__
|
||||||
|
def __init__(self, func, argdict, arglen, *args, **kwargs):
|
||||||
|
self.func = func
|
||||||
|
self._argdict = argdict
|
||||||
|
self._arglen = arglen
|
||||||
|
self._stargs = args
|
||||||
|
self.keywords = kwargs
|
||||||
|
def __reduce__(self):
|
||||||
|
return (self.__class__, (self.func, self._argdict, self._arglen) + self._stargs, self.keywords)
|
||||||
|
def __setstate__(self, keywords):
|
||||||
|
self.keywords = keywords
|
||||||
|
@property
|
||||||
|
def args(self):
|
||||||
|
return _coconut.tuple(self._argdict.get(i) for i in _coconut.range(self._arglen)) + self._stargs
|
||||||
|
def __call__(self, *args, **kwargs):
|
||||||
|
callargs = []
|
||||||
|
argind = 0
|
||||||
|
for i in _coconut.range(self._arglen):
|
||||||
|
if i in self._argdict:
|
||||||
|
callargs.append(self._argdict[i])
|
||||||
|
elif argind >= _coconut.len(args):
|
||||||
|
raise _coconut.TypeError("expected at least " + _coconut.str(self._arglen - _coconut.len(self._argdict)) + " argument(s) to " + _coconut.repr(self))
|
||||||
|
else:
|
||||||
|
callargs.append(args[argind])
|
||||||
|
argind += 1
|
||||||
|
callargs += self._stargs
|
||||||
|
callargs += args[argind:]
|
||||||
|
kwargs.update(self.keywords)
|
||||||
|
return self.func(*callargs, **kwargs)
|
||||||
|
def __repr__(self):
|
||||||
|
args = []
|
||||||
|
for i in _coconut.range(self._arglen):
|
||||||
|
if i in self._argdict:
|
||||||
|
args.append(_coconut.repr(self._argdict[i]))
|
||||||
|
else:
|
||||||
|
args.append("?")
|
||||||
|
for arg in self._stargs:
|
||||||
|
args.append(_coconut.repr(arg))
|
||||||
|
return _coconut.repr(self.func) + "$(" + ", ".join(args) + ")"
|
||||||
|
def consume(iterable, keep_last=0):
|
||||||
|
"""consume(iterable, keep_last) fully exhausts iterable and return the last keep_last elements."""
|
||||||
|
return _coconut.collections.deque(iterable, maxlen=keep_last)
|
||||||
|
class starmap(_coconut.itertools.starmap):
|
||||||
|
__slots__ = ("func", "iter")
|
||||||
|
if hasattr(_coconut.itertools.starmap, "__doc__"):
|
||||||
|
__doc__ = _coconut.itertools.starmap.__doc__
|
||||||
|
def __new__(cls, function, iterable):
|
||||||
|
new_map = _coconut.itertools.starmap.__new__(cls, function, iterable)
|
||||||
|
new_map.func = function
|
||||||
|
new_map.iter = iterable
|
||||||
|
return new_map
|
||||||
|
def __getitem__(self, index):
|
||||||
|
if _coconut.isinstance(index, _coconut.slice):
|
||||||
|
return self.__class__(self.func, _coconut_igetitem(self.iter, index))
|
||||||
|
return self.func(*_coconut_igetitem(self.iter, index))
|
||||||
|
def __reversed__(self):
|
||||||
|
return self.__class__(self.func, *_coconut_reversed(self.iter))
|
||||||
|
def __len__(self):
|
||||||
|
return _coconut.len(self.iter)
|
||||||
|
def __repr__(self):
|
||||||
|
return "starmap(%r, %r)" % (self.func, self.iter)
|
||||||
|
def __reduce__(self):
|
||||||
|
return (self.__class__, (self.func, self.iter))
|
||||||
|
def __reduce_ex__(self, _):
|
||||||
|
return self.__reduce__()
|
||||||
|
def __copy__(self):
|
||||||
|
return self.__class__(self.func, _coconut.copy.copy(self.iter))
|
||||||
|
def __fmap__(self, func):
|
||||||
|
return self.__class__(_coconut_forward_compose(self.func, func), self.iter)
|
||||||
|
def makedata(data_type, *args):
|
||||||
|
"""Construct an object of the given data_type containing the given arguments."""
|
||||||
|
if _coconut.hasattr(data_type, "_make") and _coconut.issubclass(data_type, _coconut.tuple):
|
||||||
|
return data_type._make(args)
|
||||||
|
if _coconut.issubclass(data_type, (_coconut.map, _coconut.range, _coconut.abc.Iterator)):
|
||||||
|
return args
|
||||||
|
if _coconut.issubclass(data_type, _coconut.str):
|
||||||
|
return "".join(args)
|
||||||
|
return data_type(args)
|
||||||
|
def datamaker(data_type):
|
||||||
|
"""DEPRECATED: Use makedata instead."""
|
||||||
|
return _coconut.functools.partial(makedata, data_type)
|
||||||
|
def fmap(func, obj):
|
||||||
|
"""fmap(func, obj) creates a copy of obj with func applied to its contents.
|
||||||
|
Override by defining obj.__fmap__(func)."""
|
||||||
|
if _coconut.hasattr(obj, "__fmap__"):
|
||||||
|
return obj.__fmap__(func)
|
||||||
|
if obj.__class__.__module__ == "numpy":
|
||||||
|
from numpy import vectorize
|
||||||
|
return vectorize(func)(obj)
|
||||||
|
return _coconut_makedata(obj.__class__, *(_coconut_starmap(func, obj.items()) if _coconut.isinstance(obj, _coconut.abc.Mapping) else _coconut_map(func, obj)))
|
||||||
|
def memoize(maxsize=None, *args, **kwargs):
|
||||||
|
"""Decorator that memoizes a function,
|
||||||
|
preventing it from being recomputed if it is called multiple times with the same arguments."""
|
||||||
|
return _coconut.functools.lru_cache(maxsize, *args, **kwargs)
|
||||||
|
_coconut_MatchError, _coconut_count, _coconut_enumerate, _coconut_makedata, _coconut_map, _coconut_reversed, _coconut_starmap, _coconut_tee, _coconut_zip, TYPE_CHECKING, reduce, takewhile, dropwhile = MatchError, count, enumerate, makedata, map, reversed, starmap, tee, zip, False, _coconut.functools.reduce, _coconut.itertools.takewhile, _coconut.itertools.dropwhile
|
18
yaltik_dsl/__init__.coco
Normal file
18
yaltik_dsl/__init__.coco
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright 2019 Fabien Bourgeois <fabien@yaltik.com>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from . import odoo
|
@ -1,3 +1,24 @@
|
|||||||
|
#!/usr/bin/env python2
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# __coconut_hash__ = 0xe22b9d74
|
||||||
|
|
||||||
|
# Compiled with Coconut version 1.4.3 [Ernest Scribbler]
|
||||||
|
|
||||||
|
# Coconut Header: -------------------------------------------------------------
|
||||||
|
|
||||||
|
from __future__ import print_function, absolute_import, unicode_literals, division
|
||||||
|
import sys as _coconut_sys, os.path as _coconut_os_path
|
||||||
|
_coconut_file_path = _coconut_os_path.dirname(_coconut_os_path.abspath(__file__))
|
||||||
|
_coconut_cached_module = _coconut_sys.modules.get(b"__coconut__")
|
||||||
|
if _coconut_cached_module is not None and _coconut_os_path.dirname(_coconut_cached_module.__file__) != _coconut_file_path:
|
||||||
|
del _coconut_sys.modules[b"__coconut__"]
|
||||||
|
_coconut_sys.path.insert(0, _coconut_file_path)
|
||||||
|
from __coconut__ import *
|
||||||
|
from __coconut__ import _coconut, _coconut_MatchError, _coconut_igetitem, _coconut_base_compose, _coconut_forward_compose, _coconut_back_compose, _coconut_forward_star_compose, _coconut_back_star_compose, _coconut_forward_dubstar_compose, _coconut_back_dubstar_compose, _coconut_pipe, _coconut_back_pipe, _coconut_star_pipe, _coconut_back_star_pipe, _coconut_dubstar_pipe, _coconut_back_dubstar_pipe, _coconut_bool_and, _coconut_bool_or, _coconut_none_coalesce, _coconut_minus, _coconut_map, _coconut_partial, _coconut_get_function_match_error, _coconut_base_pattern_func, _coconut_addpattern, _coconut_sentinel, _coconut_assert, _coconut_mark_as_match
|
||||||
|
|
||||||
|
|
||||||
|
# Compiled Coconut: -----------------------------------------------------------
|
||||||
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Copyright 2019 Fabien Bourgeois <fabien@yaltik.com>
|
# Copyright 2019 Fabien Bourgeois <fabien@yaltik.com>
|
||||||
|
117
yaltik_dsl/odoo.coco
Normal file
117
yaltik_dsl/odoo.coco
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright 2019-2020 Fabien Bourgeois <fabien@yaltik.com>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
""" Odoo XML DSL """
|
||||||
|
|
||||||
|
from .xml_base import xmlroot, xmln
|
||||||
|
|
||||||
|
# XML helpers functions and macros
|
||||||
|
|
||||||
|
odoo = lambda *args: xmlroot(xmln('odoo', {}, *args))
|
||||||
|
|
||||||
|
def data(*args):
|
||||||
|
""" Allow optional args on data tag """
|
||||||
|
if len(args) == 1:
|
||||||
|
return xmln('data', {}, *args)
|
||||||
|
return xmln('data', *args)
|
||||||
|
|
||||||
|
function = lambda *args: xmln('function', *args)
|
||||||
|
record = lambda *args: xmln('record', *args)
|
||||||
|
form = lambda *args: xmln('form', *args)
|
||||||
|
tree = lambda *args: xmln('tree', *args)
|
||||||
|
search = lambda *args: xmln('search', *args)
|
||||||
|
|
||||||
|
act_window = lambda *args: xmln('act_window', *args)
|
||||||
|
|
||||||
|
def act_window_model(model, attrs):
|
||||||
|
""" Build new act_window from model and args """
|
||||||
|
model_und = model.replace('.', '_')
|
||||||
|
model_cap = ' '.join([w.capitalize() for w in model.split('.')])
|
||||||
|
xmlid = '{:{}}'.format(model_und, '') + '_view_action'
|
||||||
|
name = '{:{}}'.format(model_cap, '') + ' Action'
|
||||||
|
attrs.update({'id': xmlid, 'name': name, 'res_model': model})
|
||||||
|
return act_window(attrs)
|
||||||
|
|
||||||
|
menuitem = lambda *args: xmln('menuitem', *args)
|
||||||
|
|
||||||
|
def menuitem_model(model, attrs):
|
||||||
|
""" Build new menuitem from model and attrs """
|
||||||
|
model_und = model.replace('.', '_')
|
||||||
|
actionid = '{:{}}'.format(model_und, '') + '_view_action'
|
||||||
|
xmlid = '{:{}}'.format(model_und, '') + '_men'
|
||||||
|
attrs.update({'id': xmlid, 'action': actionid})
|
||||||
|
return menuitem(attrs)
|
||||||
|
|
||||||
|
|
||||||
|
group = lambda *args: xmln('group', *args)
|
||||||
|
header = lambda *args: xmln('header', *args)
|
||||||
|
footer = lambda *args: xmln('footer', *args)
|
||||||
|
sheet = lambda *args: xmln('sheet', *args)
|
||||||
|
button = lambda *args: xmln('button', *args)
|
||||||
|
p = lambda *args: xmln('p', *args)
|
||||||
|
xpath = lambda *args: xmln('xpath', *args)
|
||||||
|
attribute = lambda name, value: xmln('attribute', {'name': name}, [value])
|
||||||
|
|
||||||
|
field = lambda *args: xmln('field', *args)
|
||||||
|
field_name = lambda name: field({'name': 'name'}, [name])
|
||||||
|
field_model = lambda model: field({'name': 'model'}, [model])
|
||||||
|
field_inherit = lambda xmlid: field({'name': 'inherit_id', 'ref': xmlid}, [])
|
||||||
|
field_arch = lambda *args: field({'name': 'arch', 'type': 'xml'}, *args)
|
||||||
|
|
||||||
|
filter = lambda *args: xmln('filter', *args)
|
||||||
|
|
||||||
|
view = lambda xmlid, children: record({'id': xmlid, 'model': 'ir.ui.view'}, children)
|
||||||
|
|
||||||
|
def view_def(xmlid, name, model, arch):
|
||||||
|
""" View and first fields simplification with record xmlid, name, targeted model """
|
||||||
|
return view(xmlid, [field_name(name), field_model(model), field_arch(arch)])
|
||||||
|
|
||||||
|
def view_new(view_type, model, arch):
|
||||||
|
""" View : new view definition, based on type (form, tree, ...) and model ID """
|
||||||
|
model_und = model.replace('.', '_')
|
||||||
|
model_cap = ' '.join([w.capitalize() for w in model.split('.')])
|
||||||
|
xmlid = '{:{}}'.format(model_und, '') + '_view_' + '{:{}}'.format(view_type, '')
|
||||||
|
name = '{:{}}'.format(model_cap, '') + ' ' + '{:{}}'.format(view_type.capitalize(), '')
|
||||||
|
return view_def(xmlid=xmlid, name=name, model=model, arch=arch)
|
||||||
|
|
||||||
|
def view_inherit(filename, model, inherit, arch):
|
||||||
|
""" Inherited View simplification with name of the record, xmlid for model
|
||||||
|
and inherited view """
|
||||||
|
module = filename.split('.')[2]
|
||||||
|
inherited = inherit.split('.')[1]
|
||||||
|
xmlid = '{:{}}'.format(inherited, '') + '_inherit_' + '{:{}}'.format(
|
||||||
|
module, '')
|
||||||
|
model_cap = ' '.join([w.capitalize() for w in model.split('.')])
|
||||||
|
name = '{:{}}'.format(model_cap, '') + ' Adaptations'
|
||||||
|
return view(xmlid, [field_name(name), field_model(model),
|
||||||
|
field_inherit(inherit), field_arch(arch)])
|
||||||
|
|
||||||
|
def actions_server_code(xmlid, name, modelref, code):
|
||||||
|
""" Server actions of type code """
|
||||||
|
return record({'id': xmlid, 'model': 'ir.actions.server'}, [
|
||||||
|
field_name(name), field({'name': 'model_id', 'ref': modelref}, [
|
||||||
|
]), field({'name': 'state'}, ['code']), field({'name': 'code'}, [code])])
|
||||||
|
|
||||||
|
def client_action_multi(xmlid, name, model, action):
|
||||||
|
""" Client action multi (ir.values), with own xmlid, name, targeted model
|
||||||
|
and action """
|
||||||
|
action = u"'ir.actions.server,%d'%" + '{:{}}'.format(action, '')
|
||||||
|
return record({'id': xmlid, 'model': 'ir.values'},
|
||||||
|
[field_name(name),
|
||||||
|
field({'name': 'key2', 'eval': u"'client_action_multi'"}, []),
|
||||||
|
field({'name': 'model', 'eval': u"'" + model + u"'"}, []),
|
||||||
|
field({'name': 'value', 'eval': action})])
|
@ -1,3 +1,26 @@
|
|||||||
|
#!/usr/bin/env python2
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# __coconut_hash__ = 0x76f908d8
|
||||||
|
|
||||||
|
# Compiled with Coconut version 1.4.3 [Ernest Scribbler]
|
||||||
|
|
||||||
|
""" Odoo XML DSL """
|
||||||
|
|
||||||
|
# Coconut Header: -------------------------------------------------------------
|
||||||
|
|
||||||
|
from __future__ import print_function, absolute_import, unicode_literals, division
|
||||||
|
import sys as _coconut_sys, os.path as _coconut_os_path
|
||||||
|
_coconut_file_path = _coconut_os_path.dirname(_coconut_os_path.abspath(__file__))
|
||||||
|
_coconut_cached_module = _coconut_sys.modules.get(b"__coconut__")
|
||||||
|
if _coconut_cached_module is not None and _coconut_os_path.dirname(_coconut_cached_module.__file__) != _coconut_file_path:
|
||||||
|
del _coconut_sys.modules[b"__coconut__"]
|
||||||
|
_coconut_sys.path.insert(0, _coconut_file_path)
|
||||||
|
from __coconut__ import *
|
||||||
|
from __coconut__ import _coconut, _coconut_MatchError, _coconut_igetitem, _coconut_base_compose, _coconut_forward_compose, _coconut_back_compose, _coconut_forward_star_compose, _coconut_back_star_compose, _coconut_forward_dubstar_compose, _coconut_back_dubstar_compose, _coconut_pipe, _coconut_back_pipe, _coconut_star_pipe, _coconut_back_star_pipe, _coconut_dubstar_pipe, _coconut_back_dubstar_pipe, _coconut_bool_and, _coconut_bool_or, _coconut_none_coalesce, _coconut_minus, _coconut_map, _coconut_partial, _coconut_get_function_match_error, _coconut_base_pattern_func, _coconut_addpattern, _coconut_sentinel, _coconut_assert, _coconut_mark_as_match
|
||||||
|
|
||||||
|
|
||||||
|
# Compiled Coconut: -----------------------------------------------------------
|
||||||
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright 2019-2020 Fabien Bourgeois <fabien@yaltik.com>
|
# Copyright 2019-2020 Fabien Bourgeois <fabien@yaltik.com>
|
||||||
@ -15,9 +38,10 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
""" Odoo XML DSL """
|
|
||||||
|
|
||||||
from .xml_base import xmlroot, xmln
|
|
||||||
|
from .xml_base import xmlroot
|
||||||
|
from .xml_base import xmln
|
||||||
|
|
||||||
# XML helpers functions and macros
|
# XML helpers functions and macros
|
||||||
|
|
||||||
@ -93,25 +117,17 @@ def view_inherit(filename, model, inherit, arch):
|
|||||||
and inherited view """
|
and inherited view """
|
||||||
module = filename.split('.')[2]
|
module = filename.split('.')[2]
|
||||||
inherited = inherit.split('.')[1]
|
inherited = inherit.split('.')[1]
|
||||||
xmlid = '{:{}}'.format(inherited, '') + '_inherit_' + '{:{}}'.format(
|
xmlid = '{:{}}'.format(inherited, '') + '_inherit_' + '{:{}}'.format(module, '')
|
||||||
module, '')
|
|
||||||
model_cap = ' '.join([w.capitalize() for w in model.split('.')])
|
model_cap = ' '.join([w.capitalize() for w in model.split('.')])
|
||||||
name = '{:{}}'.format(model_cap, '') + ' Adaptations'
|
name = '{:{}}'.format(model_cap, '') + ' Adaptations'
|
||||||
return view(xmlid, [field_name(name), field_model(model),
|
return view(xmlid, [field_name(name), field_model(model), field_inherit(inherit), field_arch(arch)])
|
||||||
field_inherit(inherit), field_arch(arch)])
|
|
||||||
|
|
||||||
def actions_server_code(xmlid, name, modelref, code):
|
def actions_server_code(xmlid, name, modelref, code):
|
||||||
""" Server actions of type code """
|
""" Server actions of type code """
|
||||||
return record({'id': xmlid, 'model': 'ir.actions.server'}, [
|
return record({'id': xmlid, 'model': 'ir.actions.server'}, [field_name(name), field({'name': 'model_id', 'ref': modelref}, []), field({'name': 'state'}, ['code']), field({'name': 'code'}, [code])])
|
||||||
field_name(name), field({'name': 'model_id', 'ref': modelref}, [
|
|
||||||
]), field({'name': 'state'}, ['code']), field({'name': 'code'}, [code])])
|
|
||||||
|
|
||||||
def client_action_multi(xmlid, name, model, action):
|
def client_action_multi(xmlid, name, model, action):
|
||||||
""" Client action multi (ir.values), with own xmlid, name, targeted model
|
""" Client action multi (ir.values), with own xmlid, name, targeted model
|
||||||
and action """
|
and action """
|
||||||
action = u"'ir.actions.server,%d'%" + '{:{}}'.format(action, '')
|
action = "'ir.actions.server,%d'%" + '{:{}}'.format(action, '')
|
||||||
return record({'id': xmlid, 'model': 'ir.values'},
|
return record({'id': xmlid, 'model': 'ir.values'}, [field_name(name), field({'name': 'key2', 'eval': "'client_action_multi'"}, []), field({'name': 'model', 'eval': "'" + model + "'"}, []), field({'name': 'value', 'eval': action})])
|
||||||
[field_name(name),
|
|
||||||
field({'name': 'key2', 'eval': u"'client_action_multi'"}, []),
|
|
||||||
field({'name': 'model', 'eval': u"'" + model + u"'"}, []),
|
|
||||||
field({'name': 'value', 'eval': action})])
|
|
||||||
|
107
yaltik_dsl/test_xml_base.coco
Normal file
107
yaltik_dsl/test_xml_base.coco
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright 2019-2020 Fabien Bourgeois <fabien@yaltik.com>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
""" XML Helpers tests """
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
from xml_base import xmln, xmlroot, xmlchild
|
||||||
|
|
||||||
|
|
||||||
|
class TestXMLBase(unittest.TestCase):
|
||||||
|
""" XML Helpers tests """
|
||||||
|
|
||||||
|
def test_xmln(self):
|
||||||
|
# Tags
|
||||||
|
(xmln(), {'tag': '', 'attrs': {}, 'children': []}) |*> self.assertEquals
|
||||||
|
(xmln <| 'a tag' |> .get <| 'tag', 'a tag') |*> self.assertEquals
|
||||||
|
|
||||||
|
# Attrs
|
||||||
|
(xmln(attrs={'a good': 'one'}).get('attrs'), {'a good': 'one'}) |*> self.assertEquals
|
||||||
|
(xmln <**| {'attrs': {'a good': 'one'}} |> .get <| 'attrs', {'a good': 'one'}) |*> self.assertEquals
|
||||||
|
|
||||||
|
# Childrens
|
||||||
|
attrs ={'children': [1, 2, 3]}
|
||||||
|
(xmln <**| attrs |> .get <| 'children' == [1, 2, 3]) |> self.assertTrue
|
||||||
|
|
||||||
|
attrs = {'children': 'Some text'}
|
||||||
|
(xmln <**| attrs |> .get <| 'children' == ['Some text']) |> self.assertTrue
|
||||||
|
|
||||||
|
try:
|
||||||
|
xmln <**| {'children': False}
|
||||||
|
except TypeError as err:
|
||||||
|
('Invalid arguments', err.message) |*> self.assertIn
|
||||||
|
|
||||||
|
|
||||||
|
def test_xmlchild(self):
|
||||||
|
parent = {'tag': 'root', 'attrs': {}, 'children': []} |> xmlroot
|
||||||
|
xmlc_par = xmlchild$ <| parent
|
||||||
|
|
||||||
|
(xmlc_par <| []) `self.assertEquals` None
|
||||||
|
try:
|
||||||
|
xmlc_par <| False
|
||||||
|
except TypeError as err:
|
||||||
|
'is not iterable' `self.assertIn` err.message
|
||||||
|
|
||||||
|
xmlc_par <| ['some text']
|
||||||
|
parent.text `self.assertEquals` 'some text'
|
||||||
|
|
||||||
|
xmlc_par <| [{'tag': 't', 'attrs': {'a': 'b'}, 'children': []}]
|
||||||
|
child = parent.iter <| 't' |> next
|
||||||
|
child.tag `self.assertEquals` 't'
|
||||||
|
child.attrib `self.assertEquals` {'a': 'b'}
|
||||||
|
(child |> list) `self.assertEquals` []
|
||||||
|
|
||||||
|
xmlc_par <| [{'tag': 't2', 'attrs': {1: 2}, 'children': []}]
|
||||||
|
child = parent.iter <| 't2' |> next
|
||||||
|
child.attrib `self.assertEquals` {'1': '2'}
|
||||||
|
|
||||||
|
xmlc_par <| [{'tag': 'tchildren', 'attrs': {},
|
||||||
|
'children': [{'tag': 'subchild', 'attrs': {}, 'children': []}]}]
|
||||||
|
child = parent.iter <| 'tchildren' |> next
|
||||||
|
subchildren = (child |> list)
|
||||||
|
(subchildren |> len) `self.assertEquals` 1
|
||||||
|
subchildren[0].tag `self.assertEquals` 'subchild'
|
||||||
|
|
||||||
|
|
||||||
|
def test_xmlroot(self):
|
||||||
|
root = {'tag': 'root', 'attrs': {}, 'children': []} |> xmlroot
|
||||||
|
isinstance <*| (root, ET.Element) |> self.assertTrue
|
||||||
|
|
||||||
|
try:
|
||||||
|
False |> xmlroot
|
||||||
|
except TypeError as err:
|
||||||
|
('has no attribute', err.message) |*> self.assertIn
|
||||||
|
try:
|
||||||
|
{} |> xmlroot
|
||||||
|
except KeyError as err:
|
||||||
|
('tag', err.message) |*> self.assertIn
|
||||||
|
try:
|
||||||
|
{'tag': 'root'} |> xmlroot
|
||||||
|
except KeyError as err:
|
||||||
|
('attrs', err.message) |*> self.assertIn
|
||||||
|
try:
|
||||||
|
{'tag': 'root', 'attrs': {}} |> xmlroot
|
||||||
|
except KeyError as err:
|
||||||
|
('children', err.message) |*> self.assertIn
|
||||||
|
|
||||||
|
|
||||||
|
def test_xml_write(self): pass
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
132
yaltik_dsl/test_xml_base.py
Normal file
132
yaltik_dsl/test_xml_base.py
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
#!/usr/bin/env python2
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# __coconut_hash__ = 0xf82711d8
|
||||||
|
|
||||||
|
# Compiled with Coconut version 1.4.3 [Ernest Scribbler]
|
||||||
|
|
||||||
|
""" XML Helpers tests """
|
||||||
|
|
||||||
|
# Coconut Header: -------------------------------------------------------------
|
||||||
|
|
||||||
|
from __future__ import print_function, absolute_import, unicode_literals, division
|
||||||
|
import sys as _coconut_sys, os.path as _coconut_os_path
|
||||||
|
_coconut_file_path = _coconut_os_path.dirname(_coconut_os_path.abspath(__file__))
|
||||||
|
_coconut_cached_module = _coconut_sys.modules.get(b"__coconut__")
|
||||||
|
if _coconut_cached_module is not None and _coconut_os_path.dirname(_coconut_cached_module.__file__) != _coconut_file_path:
|
||||||
|
del _coconut_sys.modules[b"__coconut__"]
|
||||||
|
_coconut_sys.path.insert(0, _coconut_file_path)
|
||||||
|
from __coconut__ import *
|
||||||
|
from __coconut__ import _coconut, _coconut_MatchError, _coconut_igetitem, _coconut_base_compose, _coconut_forward_compose, _coconut_back_compose, _coconut_forward_star_compose, _coconut_back_star_compose, _coconut_forward_dubstar_compose, _coconut_back_dubstar_compose, _coconut_pipe, _coconut_back_pipe, _coconut_star_pipe, _coconut_back_star_pipe, _coconut_dubstar_pipe, _coconut_back_dubstar_pipe, _coconut_bool_and, _coconut_bool_or, _coconut_none_coalesce, _coconut_minus, _coconut_map, _coconut_partial, _coconut_get_function_match_error, _coconut_base_pattern_func, _coconut_addpattern, _coconut_sentinel, _coconut_assert, _coconut_mark_as_match
|
||||||
|
|
||||||
|
|
||||||
|
# Compiled Coconut: -----------------------------------------------------------
|
||||||
|
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright 2019-2020 Fabien Bourgeois <fabien@yaltik.com>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
from xml_base import xmln
|
||||||
|
from xml_base import xmlroot
|
||||||
|
from xml_base import xmlchild
|
||||||
|
|
||||||
|
|
||||||
|
class TestXMLBase(unittest.TestCase):
|
||||||
|
""" XML Helpers tests """
|
||||||
|
|
||||||
|
def test_xmln(self):
|
||||||
|
# Tags
|
||||||
|
(self.assertEquals)(*(xmln(), {'tag': '', 'attrs': {}, 'children': []}))
|
||||||
|
(self.assertEquals)(*((((xmln)('a tag')).get)('tag'), 'a tag'))
|
||||||
|
|
||||||
|
# Attrs
|
||||||
|
(self.assertEquals)(*(xmln(attrs={'a good': 'one'}).get('attrs'), {'a good': 'one'}))
|
||||||
|
(self.assertEquals)(*((((xmln)(**{'attrs': {'a good': 'one'}})).get)('attrs'), {'a good': 'one'}))
|
||||||
|
|
||||||
|
# Childrens
|
||||||
|
attrs = {'children': [1, 2, 3]}
|
||||||
|
(self.assertTrue)(((((xmln)(**attrs)).get)('children') == [1, 2, 3]))
|
||||||
|
|
||||||
|
attrs = {'children': 'Some text'}
|
||||||
|
(self.assertTrue)(((((xmln)(**attrs)).get)('children') == ['Some text']))
|
||||||
|
|
||||||
|
try:
|
||||||
|
(xmln)(**{'children': False})
|
||||||
|
except TypeError as err:
|
||||||
|
(self.assertIn)(*('Invalid arguments', err.message))
|
||||||
|
|
||||||
|
|
||||||
|
def test_xmlchild(self):
|
||||||
|
parent = (xmlroot)({'tag': 'root', 'attrs': {}, 'children': []})
|
||||||
|
xmlc_par = (_coconut.functools.partial(_coconut.functools.partial, xmlchild))(parent)
|
||||||
|
|
||||||
|
(self.assertEquals)(((xmlc_par)([])), None)
|
||||||
|
try:
|
||||||
|
(xmlc_par)(False)
|
||||||
|
except TypeError as err:
|
||||||
|
(self.assertIn)('is not iterable', err.message)
|
||||||
|
|
||||||
|
(xmlc_par)(['some text'])
|
||||||
|
(self.assertEquals)(parent.text, 'some text')
|
||||||
|
|
||||||
|
(xmlc_par)([{'tag': 't', 'attrs': {'a': 'b'}, 'children': []}])
|
||||||
|
child = (next)((parent.iter)('t'))
|
||||||
|
(self.assertEquals)(child.tag, 't')
|
||||||
|
(self.assertEquals)(child.attrib, {'a': 'b'})
|
||||||
|
(self.assertEquals)(((list)(child)), [])
|
||||||
|
|
||||||
|
(xmlc_par)([{'tag': 't2', 'attrs': {1: 2}, 'children': []}])
|
||||||
|
child = (next)((parent.iter)('t2'))
|
||||||
|
(self.assertEquals)(child.attrib, {'1': '2'})
|
||||||
|
|
||||||
|
(xmlc_par)([{'tag': 'tchildren', 'attrs': {}, 'children': [{'tag': 'subchild', 'attrs': {}, 'children': []}]}])
|
||||||
|
child = (next)((parent.iter)('tchildren'))
|
||||||
|
subchildren = ((list)(child))
|
||||||
|
(self.assertEquals)(((len)(subchildren)), 1)
|
||||||
|
(self.assertEquals)(subchildren[0].tag, 'subchild')
|
||||||
|
|
||||||
|
|
||||||
|
def test_xmlroot(self):
|
||||||
|
root = (xmlroot)({'tag': 'root', 'attrs': {}, 'children': []})
|
||||||
|
(self.assertTrue)((isinstance)(*(root, ET.Element)))
|
||||||
|
|
||||||
|
try:
|
||||||
|
(xmlroot)(False)
|
||||||
|
except TypeError as err:
|
||||||
|
(self.assertIn)(*('has no attribute', err.message))
|
||||||
|
try:
|
||||||
|
(xmlroot)({})
|
||||||
|
except KeyError as err:
|
||||||
|
(self.assertIn)(*('tag', err.message))
|
||||||
|
try:
|
||||||
|
(xmlroot)({'tag': 'root'})
|
||||||
|
except KeyError as err:
|
||||||
|
(self.assertIn)(*('attrs', err.message))
|
||||||
|
try:
|
||||||
|
(xmlroot)({'tag': 'root', 'attrs': {}})
|
||||||
|
except KeyError as err:
|
||||||
|
(self.assertIn)(*('children', err.message))
|
||||||
|
|
||||||
|
|
||||||
|
def test_xml_write(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
78
yaltik_dsl/xml_base.coco
Normal file
78
yaltik_dsl/xml_base.coco
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright 2019-2020 Fabien Bourgeois <fabien@yaltik.com>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
""" XML helpers and macros """
|
||||||
|
|
||||||
|
from os import path
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
from xml.dom import minidom
|
||||||
|
from typing import Dict, List, Union, Any
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: ADT for XMLchild children**s**
|
||||||
|
# REF xml_write
|
||||||
|
|
||||||
|
data XMLChildren(clist: List[Union[XMLDict, XMLText]])
|
||||||
|
|
||||||
|
data XMLText(text: Union[str, unicode])
|
||||||
|
data XMLDict(tag: str, attrs: Dict[str, str], children: XMLChildren)
|
||||||
|
|
||||||
|
data XMLTag(tag: str)
|
||||||
|
data XMLAttrs(attrs: Dict[str, str])
|
||||||
|
|
||||||
|
def xmlroot(tree: Dict[str, Any]) -> ET.Element:
|
||||||
|
""" Special process for root XML Node """
|
||||||
|
rootel = (tree['tag'], tree['attrs']) |*> ET.Element
|
||||||
|
if 'children' in tree:
|
||||||
|
(rootel, tree['children']) |*> xmlchild
|
||||||
|
return rootel
|
||||||
|
|
||||||
|
def xmlchild(parent: ET.Element, children: Any) -> None:
|
||||||
|
""" Handling of children (ie non root) XML Nodes with/o text and
|
||||||
|
subchildren (recursive) """
|
||||||
|
match _ is (str, unicode) in children:
|
||||||
|
parent.text = children
|
||||||
|
return
|
||||||
|
match _ is dict in children:
|
||||||
|
attrs = {unicode(k): unicode(v) for [k, v] in children['attrs'].items()}
|
||||||
|
new_parent = (parent, children['tag'], attrs) |*> ET.SubElement
|
||||||
|
subchildren = children['children']
|
||||||
|
if subchildren:
|
||||||
|
(new_parent, subchildren) |*> xmlchild
|
||||||
|
match _ is list in children:
|
||||||
|
((xmlchild$ <| parent), children) |*> map |> consume
|
||||||
|
|
||||||
|
|
||||||
|
def xmln(tag: str = '',
|
||||||
|
attrs: Dict[str, str] = {},
|
||||||
|
children: Union[str, List] = []) -> Dict:
|
||||||
|
""" XMLNode with default children, not attributes """
|
||||||
|
match c is str in children:
|
||||||
|
return {'tag': tag, 'attrs': attrs, 'children': [c]}
|
||||||
|
else: match c is list in children:
|
||||||
|
return {'tag': tag, 'attrs': attrs, 'children': c}
|
||||||
|
else:
|
||||||
|
raise TypeError('Invalid arguments for xmln')
|
||||||
|
|
||||||
|
def xml_write(filepath, tree):
|
||||||
|
""" Write XML file according to filename and given tree """
|
||||||
|
if filepath.endswith('.py'): # if .pyc, no need to generate XML
|
||||||
|
output_xml = minidom.parseString(ET.tostring(tree)).toprettyxml(indent=' ')
|
||||||
|
output_path = path.dirname(path.abspath(filepath))
|
||||||
|
fpath = '%s/%s' % (output_path, path.basename(filepath).replace('.py', '_views.xml'))
|
||||||
|
with open(fpath, 'w') as output_file:
|
||||||
|
output_file.write(output_xml)
|
@ -1,3 +1,26 @@
|
|||||||
|
#!/usr/bin/env python2
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# __coconut_hash__ = 0xd881e1a
|
||||||
|
|
||||||
|
# Compiled with Coconut version 1.4.3 [Ernest Scribbler]
|
||||||
|
|
||||||
|
""" XML helpers and macros """
|
||||||
|
|
||||||
|
# Coconut Header: -------------------------------------------------------------
|
||||||
|
|
||||||
|
from __future__ import print_function, absolute_import, unicode_literals, division
|
||||||
|
import sys as _coconut_sys, os.path as _coconut_os_path
|
||||||
|
_coconut_file_path = _coconut_os_path.dirname(_coconut_os_path.abspath(__file__))
|
||||||
|
_coconut_cached_module = _coconut_sys.modules.get(b"__coconut__")
|
||||||
|
if _coconut_cached_module is not None and _coconut_os_path.dirname(_coconut_cached_module.__file__) != _coconut_file_path:
|
||||||
|
del _coconut_sys.modules[b"__coconut__"]
|
||||||
|
_coconut_sys.path.insert(0, _coconut_file_path)
|
||||||
|
from __coconut__ import *
|
||||||
|
from __coconut__ import _coconut, _coconut_MatchError, _coconut_igetitem, _coconut_base_compose, _coconut_forward_compose, _coconut_back_compose, _coconut_forward_star_compose, _coconut_back_star_compose, _coconut_forward_dubstar_compose, _coconut_back_dubstar_compose, _coconut_pipe, _coconut_back_pipe, _coconut_star_pipe, _coconut_back_star_pipe, _coconut_dubstar_pipe, _coconut_back_dubstar_pipe, _coconut_bool_and, _coconut_bool_or, _coconut_none_coalesce, _coconut_minus, _coconut_map, _coconut_partial, _coconut_get_function_match_error, _coconut_base_pattern_func, _coconut_addpattern, _coconut_sentinel, _coconut_assert, _coconut_mark_as_match
|
||||||
|
|
||||||
|
|
||||||
|
# Compiled Coconut: -----------------------------------------------------------
|
||||||
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright 2019-2020 Fabien Bourgeois <fabien@yaltik.com>
|
# Copyright 2019-2020 Fabien Bourgeois <fabien@yaltik.com>
|
||||||
@ -15,40 +38,107 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
""" XML helpers and macros """
|
|
||||||
|
|
||||||
from os import path
|
from os import path
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
from xml.dom import minidom
|
from xml.dom import minidom
|
||||||
|
from typing import Dict
|
||||||
|
from typing import List
|
||||||
|
from typing import Union
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
def xmlroot(tree):
|
# TODO: ADT for XMLchild children**s**
|
||||||
|
|
||||||
|
class XMLChildren(_coconut.typing.NamedTuple("XMLChildren", [("clist", 'List[Union[XMLChildDict, XMLChildText]]')]), _coconut.object):
|
||||||
|
__slots__ = ()
|
||||||
|
__ne__ = _coconut.object.__ne__
|
||||||
|
def __eq__(self, other):
|
||||||
|
return self.__class__ is other.__class__ and _coconut.tuple.__eq__(self, other)
|
||||||
|
def __hash__(self):
|
||||||
|
return _coconut.tuple.__hash__(self) ^ hash(self.__class__)
|
||||||
|
|
||||||
|
class XMLChildText(_coconut.typing.NamedTuple("XMLChildText", [("text", 'Union[str, unicode]')]), _coconut.object):
|
||||||
|
__slots__ = ()
|
||||||
|
__ne__ = _coconut.object.__ne__
|
||||||
|
def __eq__(self, other):
|
||||||
|
return self.__class__ is other.__class__ and _coconut.tuple.__eq__(self, other)
|
||||||
|
def __hash__(self):
|
||||||
|
return _coconut.tuple.__hash__(self) ^ hash(self.__class__)
|
||||||
|
|
||||||
|
class XMLChildDict(_coconut.typing.NamedTuple("XMLChildDict", [("tag", 'str'), ("attrs", 'Dict[str, str]'), ("children", 'XMLChildren')]), _coconut.object):
|
||||||
|
__slots__ = ()
|
||||||
|
__ne__ = _coconut.object.__ne__
|
||||||
|
def __eq__(self, other):
|
||||||
|
return self.__class__ is other.__class__ and _coconut.tuple.__eq__(self, other)
|
||||||
|
def __hash__(self):
|
||||||
|
return _coconut.tuple.__hash__(self) ^ hash(self.__class__)
|
||||||
|
|
||||||
|
|
||||||
|
def xmlroot(tree # type: Dict[str, Any]
|
||||||
|
):
|
||||||
|
# type: (...) -> ET.Element
|
||||||
""" Special process for root XML Node """
|
""" Special process for root XML Node """
|
||||||
rootel = ET.Element(tree['tag'], tree['attrs'])
|
rootel = (ET.Element)(*(tree['tag'], tree['attrs']))
|
||||||
children = tree['children']
|
if 'children' in tree:
|
||||||
if children:
|
(xmlchild)(*(rootel, tree['children']))
|
||||||
xmlchild(rootel, children)
|
|
||||||
return rootel
|
return rootel
|
||||||
|
|
||||||
|
def xmlchild(parent, # type: ET.Element
|
||||||
def xmlchild(parent, children):
|
children # type: Any
|
||||||
|
):
|
||||||
|
# type: (...) -> None
|
||||||
""" Handling of children (ie non root) XML Nodes with/o text and
|
""" Handling of children (ie non root) XML Nodes with/o text and
|
||||||
subchildren (recursive) """
|
subchildren (recursive) """
|
||||||
for child in children:
|
_coconut_match_to = children
|
||||||
if isinstance(child, (str, unicode)):
|
_coconut_match_check = False
|
||||||
parent.text = child
|
if _coconut.isinstance(_coconut_match_to, (str, unicode)):
|
||||||
else:
|
_coconut_match_check = True
|
||||||
attrs = {unicode(k): unicode(v) for [k, v] in child['attrs'].items()}
|
if _coconut_match_check:
|
||||||
new_parent = ET.SubElement(parent, child['tag'], attrs)
|
parent.text = children
|
||||||
subchildren = child['children']
|
return
|
||||||
|
_coconut_match_to = children
|
||||||
|
_coconut_match_check = False
|
||||||
|
if _coconut.isinstance(_coconut_match_to, dict):
|
||||||
|
_coconut_match_check = True
|
||||||
|
if _coconut_match_check:
|
||||||
|
attrs = dict(((unicode(k)), (unicode(v))) for [k, v] in children['attrs'].items())
|
||||||
|
new_parent = (ET.SubElement)(*(parent, children['tag'], attrs))
|
||||||
|
subchildren = children['children']
|
||||||
if subchildren:
|
if subchildren:
|
||||||
xmlchild(new_parent, subchildren)
|
(xmlchild)(*(new_parent, subchildren))
|
||||||
|
_coconut_match_to = children
|
||||||
|
_coconut_match_check = False
|
||||||
|
if _coconut.isinstance(_coconut_match_to, list):
|
||||||
|
_coconut_match_check = True
|
||||||
|
if _coconut_match_check:
|
||||||
|
(consume)((map)(*(((_coconut.functools.partial(_coconut.functools.partial, xmlchild))(parent)), children)))
|
||||||
|
|
||||||
|
|
||||||
def xmln(tag='', attrs=None, children=None, text=False):
|
def xmln(tag='', # type: str
|
||||||
|
attrs={}, # type: Dict[str, str]
|
||||||
|
children=[] # type: Union[str, List]
|
||||||
|
):
|
||||||
|
# type: (...) -> Dict
|
||||||
""" XMLNode with default children, not attributes """
|
""" XMLNode with default children, not attributes """
|
||||||
children = ([text] if text else children) or []
|
_coconut_match_to = children
|
||||||
return {'tag': tag, 'attrs': attrs or {}, 'children': children}
|
_coconut_match_check = False
|
||||||
|
if _coconut.isinstance(_coconut_match_to, str):
|
||||||
|
c = _coconut_match_to
|
||||||
|
_coconut_match_check = True
|
||||||
|
if _coconut_match_check:
|
||||||
|
return {'tag': tag, 'attrs': attrs, 'children': [c]}
|
||||||
|
else:
|
||||||
|
_coconut_match_to = children
|
||||||
|
_coconut_match_check = False
|
||||||
|
if _coconut.isinstance(_coconut_match_to, list):
|
||||||
|
c = _coconut_match_to
|
||||||
|
_coconut_match_check = True
|
||||||
|
if _coconut_match_check:
|
||||||
|
return {'tag': tag, 'attrs': attrs, 'children': c}
|
||||||
|
else:
|
||||||
|
raise TypeError('Invalid arguments for xmln')
|
||||||
|
|
||||||
def xml_write(filepath, tree):
|
def xml_write(filepath, tree):
|
||||||
""" Write XML file according to filename and given tree """
|
""" Write XML file according to filename and given tree """
|
||||||
|
Loading…
x
Reference in New Issue
Block a user