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

Commit

Permalink
can run tests
Browse files Browse the repository at this point in the history
  • Loading branch information
lsbardel committed Nov 2, 2016
1 parent 9c74925 commit 0475f03
Show file tree
Hide file tree
Showing 53 changed files with 403 additions and 417 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -2,6 +2,7 @@
*.pyd
*.so
.eggs
*.log
*.egg-info
_dep.py

Expand Down
19 changes: 19 additions & 0 deletions .travis.yml
@@ -0,0 +1,19 @@
language: python

python:
- 3.5.2
- 3.6-dev

install:
- sudo apt-get install enchant
- pip install -r requirements-dev.txt

script:
- python setup.py test --coverage -q
- flake8
- if [[ $TRAVIS_PYTHON_VERSION == 3.5.2 ]]; then python setup.py test --coveralls; fi
- python setup.py bench


notifications:
email: false
16 changes: 13 additions & 3 deletions dynts/api/__init__.py
@@ -1,12 +1,22 @@
from .data import Data
from .timeseries import TimeSeries, is_timeseries
from .main import timeseries
from .names import tsname
from .timeseries import TimeSeries, is_timeseries, ts_bin_op
from .scatter import Scatter, is_scatter
from .main import timeseries, randomts
from ..dsl import parse, evaluate
from .. import backends # noqa


__all__ = [
'Data',
'tsname',
'TimeSeries',
'is_timeseries',
'timeseries'
'Scatter',
'is_scatter',
'timeseries',
'randomts',
'ts_bin_op',
'parse',
'evaluate'
]
28 changes: 14 additions & 14 deletions dynts/api/main.py
@@ -1,7 +1,7 @@
from importlib import import_module

from ..conf import settings
from ..exc import InvalidBackEnd
from ..utils.populate import datepopulate, populate
from .timeseries import BACKENDS


def timeseries(name='', backend=None, date=None, data=None, **kwargs):
Expand All @@ -17,16 +17,16 @@ def timeseries(name='', backend=None, date=None, data=None, **kwargs):
:parameter data: optional iterable over data.
'''
backend = backend or settings.backend
bname = BACKENDS.get(backend, None)
if bname:
bmodule = 'dynts.backends.%s' % bname
else:
bmodule = backend
module = import_module(bmodule)
name = name or bmodule
try:
factory = getattr(module, 'TimeSeries')
except AttributeError:
TS = BACKENDS.get(backend)
if not TS:
raise InvalidBackEnd(
'Could not find a TimeSeries class in module %s' % bmodule)
return factory(name = name, date = date, data = data, **kwargs)
'Could not find a TimeSeries class %s' % backend
)
return TS(name=name, date=date, data=data, **kwargs)


def randomts(size=100, cols=1, start=None, delta=1,
generator=None, backend=None, name='randomts'):
dates = datepopulate(size, start=start, delta=delta)
data = populate(size, cols=cols, generator=generator)
return timeseries(name=name, backend=backend, date=dates, data=data)
16 changes: 16 additions & 0 deletions dynts/api/names.py
@@ -0,0 +1,16 @@
from functools import reduce

from ..conf import settings


def tsname(*names):
sp = settings.splittingnames
return reduce(lambda x, y: '%s%s%s' % (x, sp, y), names)


def composename(name, *names, **kwargs):
sp = settings.splittingnames
kw = ','.join(('{0}={1}'.format(*v) for v in kwargs.items()))
if kw:
kw = ',' + kw
return sp.join(('{0}({1}{2})'.format(name, x, kw) for x in names))
64 changes: 9 additions & 55 deletions dynts/api/operators.py
@@ -1,6 +1,5 @@
import numpy as np

from ..conf import settings
from ..exc import ExpressionError


Expand All @@ -12,7 +11,7 @@
}


def _get_op(op_name):
def op_get(op_name):
global _ops
op = _ops.get(op_name, None)
if op is None:
Expand Down Expand Up @@ -49,7 +48,7 @@ def applyfn(op, v1, v2, fill_vec):
def op_or_missing(a,b):
try:
result = op(a,b)
except Exception as e:
except Exception:
result = None
if result is None:
result = fill_vec
Expand Down Expand Up @@ -78,7 +77,7 @@ def _create_fill_vec(ts, fill_fn):
return fill


def _handle_scalar_ts(op_name, op, scalar, ts, fill_fn):
def op_scalar_ts(op_name, op, scalar, ts, fill_fn):
fill_vec = _create_fill_vec(ts, fill_fn)
values = ts.values()
shape = values.shape
Expand All @@ -89,7 +88,7 @@ def _handle_scalar_ts(op_name, op, scalar, ts, fill_fn):
return dts, result


def _handle_ts_scalar(op_name, op, ts, scalar, fill_fn):
def op_ts_scalar(op_name, op, ts, scalar, fill_fn):
values = ts.values()
if values is not None:
fill_vec = _create_fill_vec(ts, fill_fn)
Expand All @@ -102,9 +101,12 @@ def _handle_ts_scalar(op_name, op, ts, scalar, fill_fn):
return None, None


def _handle_ts_ts(op_name, op, ts, ts2, all, fill_fn):
def op_ts_ts(op_name, op, ts, ts2, all, fill_fn):
if ts.count() != ts2.count():
raise ExpressionError("Cannot %s two timeseries with different number of series." % op_name)
raise ExpressionError(
"Cannot %s two timeseries with different number of series."
% op_name
)
dts1 = set(ts.dates())
if all:
indx = dts1.union(ts2.dates())
Expand All @@ -126,51 +128,3 @@ def _handle_ts_ts(op_name, op, ts, ts2, all, fill_fn):
new_ts = hash.getts()
rt = zip(*new_ts.items())
return rt


def _handle_ts_or_scalar(op_name, ts1, ts2, all=True, fill=None, name=None):
'''Entry point for any arithmetic type function performed on a timeseries
and/or a scalar.
op_name - name of the function to be performed
ts1, ts2 - timeseries or scalars that the function is to performed over
all - whether all dates should be included in the result
fill - the value that should be used to represent "missing values"
name - the name of the resulting time series
'''
from dynts import istimeseries
op = _get_op(op_name)
fill = fill if fill is not None else settings.missing_value
if hasattr(fill,'__call__'):
fill_fn = fill
else:
fill_fn = lambda : fill

name = name or '%s(%s,%s)' % (op_name,ts1,ts2)
ts = None
if istimeseries(ts1):
ts = ts1
if istimeseries(ts2):
dts, data = _handle_ts_ts(op_name, op, ts1, ts2, all, fill_fn)

else:
dts, data = _handle_ts_scalar(op_name, op, ts1, ts2, fill_fn)
else:
if istimeseries(ts2):
ts = ts2
dts, data = _handle_scalar_ts(op_name, op, ts1, ts2, fill_fn)
else:
return op(ts1,ts2)

return ts.clone(date = dts, data = data, name = name)


def ts_fn(op_name):
def fn(*args, **kwargs):
return _handle_ts_or_scalar(op_name, *args, **kwargs)
return fn


add = ts_fn('add')
sub = ts_fn('sub')
mul = ts_fn('mul')
div = ts_fn('div')
4 changes: 4 additions & 0 deletions dynts/api/scatter.py
Expand Up @@ -12,6 +12,10 @@ def __init__(self, name = '', data = None, lines = True,
self.data = data


def is_scatter(value):
return isinstance(value, Scatter)


class Scatter(Data):
'''A :class:`dynts.DynData` class for 2-dimensional series of data
with an extra dimension which contain further information for
Expand Down
85 changes: 66 additions & 19 deletions dynts/api/timeseries.py
@@ -1,25 +1,20 @@
import numpy as np

from dynts.utils import laggeddates, ashash, asbtree, asarray
from .data import Data
from . import operators
from ..conf import settings
from ..exc import DyntsException, NotAvailable
from ..utils.wrappers import ashash, asbtree, asarray
from .operators import op_get, op_ts_ts, op_ts_scalar, op_scalar_ts

nan = np.nan

ops = operators._ops
ts_bin_op = operators._handle_ts_or_scalar
object_type = np.dtype(object)


def is_timeseries(value):
return isinstance(value, TimeSeries)


BACKENDS = {
'zoo': 'zoo',
'numpy': 'tsnumpy',
}
BACKENDS = {}


class TSmeta(type):
Expand All @@ -33,6 +28,56 @@ def __new__(cls, name, bases, attrs):
return klass


def ts_merge(series):
'''Merge timeseries into a new :class:`~.TimeSeries` instance.
:parameter series: an iterable over :class:`~.TimeSeries`.
'''
series = iter(series)
ts = next(series)
return ts.merge(series)


def ts_bin_op(op_name, ts1, ts2, all=True, fill=None, name=None):
'''Entry point for any arithmetic type function performed on a timeseries
and/or a scalar.
op_name - name of the function to be performed
ts1, ts2 - timeseries or scalars that the function is to performed over
all - whether all dates should be included in the result
fill - the value that should be used to represent "missing values"
name - the name of the resulting time series
'''
op = op_get(op_name)
fill = fill if fill is not None else settings.missing_value
if hasattr(fill,'__call__'):
fill_fn = fill
else:
fill_fn = lambda: fill

name = name or '%s(%s,%s)' % (op_name, ts1, ts2)
if is_timeseries(ts1):
ts = ts1
if is_timeseries(ts2):
dts, data = op_ts_ts(op_name, op, ts1, ts2, all, fill_fn)

else:
dts, data = op_ts_scalar(op_name, op, ts1, ts2, fill_fn)
else:
if is_timeseries(ts2):
ts = ts2
dts, data = op_scalar_ts(op_name, op, ts1, ts2, fill_fn)
else:
return op(ts1, ts2)

return ts.clone(date=dts, data=data, name=name)


def ts_fn(op_name):
def fn(*args, **kwargs):
return ts_bin_op(op_name, *args, **kwargs)
return fn


class TimeSeries(Data, metaclass=TSmeta):
'''A :class:`~.DynData` specialisation for timeseries.
This class expose all the main functionalities of a timeseries
Expand All @@ -50,17 +95,17 @@ class TimeSeries(Data, metaclass=TSmeta):
default_align = 'right'
_algorithms = {}

def __init__(self, name='', date=None, data=None, info=None,
def __init__(self, name=None, date=None, data=None, info=None,
dtype=np.double, **params):
super(TimeSeries,self).__init__(name, info)
super().__init__(name, info)
self._dtype = np.dtype(dtype)
self.make(date, data, **params)

__add__ = operators.add
__sub__ = operators.sub
__mul__ = operators.mul
__div__ = operators.div
__truediv__ = operators.div # Python 3
__add__ = ts_fn('add')
__sub__ = ts_fn('sub')
__mul__ = ts_fn('mul')
__div__ = ts_fn('div')
__truediv__ = ts_fn('div')

@property
def dtype(self):
Expand Down Expand Up @@ -109,9 +154,11 @@ def dates(self, desc=None):
for key in self.keys(desc=desc):
yield c(key)

def keys(self, desc = None):
'''Returns an iterable over ``raw`` keys. The keys may be different
from dates for same backend implementations.'''
def keys(self, desc=None):
'''Returns an iterable over ``raw`` keys.
Keys may be different from dates for same backend implementations.
'''
raise NotImplementedError

def values(self, desc=None):
Expand Down
3 changes: 1 addition & 2 deletions dynts/backends/np.py
Expand Up @@ -6,8 +6,7 @@

from ..api.timeseries import TimeSeries, is_timeseries
from ..lib import skiplist
from ..conf import settings
from ..utils import laggeddates, asarray
from ..utils.section import asarray


arraytype = np.ndarray
Expand Down

0 comments on commit 0475f03

Please sign in to comment.