Source code for xlref.filters
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
#
# Copyright 2020-2024 Vincenzo Arcidiacono;
# Licensed under the EUPL (the 'Licence');
# You may not use this work except in compliance with the Licence.
# You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
"""
It provides functions implementations to filter the parsed data.
"""
import numpy as np
import schedula as sh
from .errors import InvalidReference, NoFullCell
[docs]
class FiltersFactory(dict):
def __getitem__(self, item):
try:
return super(FiltersFactory, self).__getitem__(item)
except KeyError:
return lambda p, x, *args, **kw: getattr(x, item)(*args, **kw)
FILTERS = FiltersFactory({
'T': lambda parent, x: x.T,
'array': lambda parent, x, *args, **kw: np.asarray(x, *args, **kw),
})
# noinspection PyUnusedLocal
[docs]
def full(parent, x):
"""
Remove the empty value from each row of the input array.
:param parent:
Parent parser.
:type parent: xlref.parser.Ref
:param x:
Array.
:type x: list|numpy.array
:return:
Filtered array.
:rtype: list
"""
from pandas import notnull
return [list(filter(notnull, r)) for r in x]
FILTERS['full'] = full
[docs]
def ref(parent, x):
"""
If the input is a valid reference, returns the captured values otherwise
the input.
:param parent:
Parent parser.
:type parent: xlref.parser.Ref
:param x:
Input value.
:type x: object
:return:
If the input is a valid reference, returns the captured values otherwise
the input.
:rtype: object
"""
try:
x = parent.__class__(x, parent, parent.cache).values
except InvalidReference:
pass
except NoFullCell as ex:
x = ex
return x
FILTERS['ref'] = ref
[docs]
def recursive(parent, x, dtype=None):
"""
Parse recursively all values in the array.
:param parent:
Parent parser.
:type parent: xlref.parser.Ref
:param x:
Array.
:type x: list|numpy.array
:return:
Parsed array.
:rtype: numpy.array
"""
res, shape = [ref(parent, v) for v in np.ravel(x)], np.shape(x)
if dtype is None and isinstance(x, np.ndarray):
dtype = x.dtype
return np.reshape(np.asarray(res, dtype=dtype), shape)
FILTERS['recursive'] = recursive
def _kv(it):
for k, v in it:
if isinstance(k, dict):
yield from k.items()
else:
yield k, v
[docs]
def fdict(parent, x, key=None, value=None):
"""
Convert the input array into a dictionary.
:param parent:
Parent parser.
:type parent: xlref.parser.Ref
:param x:
Array.
:type x: list|numpy.array
:param key:
Filter applied to keys.
:type key: str|list
:param value:
Filter applied to values.
:type value: str|list
:return:
Parsed dictionary.
:rtype: dict
"""
from pandas import isnull
from .parser import compile_filters
x = x.items() if isinstance(x, dict) else x
it = ((v[0], v[1] if len(v) == 2 else v[1:]) for v in x if not isnull(v[0]))
key = key and compile_filters(sh.stlp(key), parent) or (lambda k: k)
value = value and compile_filters(sh.stlp(value), parent) or (lambda v: v)
return dict(_kv((key(k), value(v)) for k, v in _kv(it)))
FILTERS['dict'] = fdict