mirror of
https://github.com/wassname/catalyst.git
synced 2026-06-27 19:30:28 +08:00
TST: fix doctests to actually run
This commit is contained in:
+1
-1
@@ -43,7 +43,7 @@ before_script:
|
||||
- pip freeze | sort
|
||||
script:
|
||||
- flake8 zipline tests
|
||||
- nosetests --with-coverage tests/
|
||||
- nosetests --with-coverage
|
||||
# deactive env to get access to anaconda command
|
||||
- source deactivate
|
||||
- if [[ "$TRAVIS_SECURE_ENV_VARS" = "true" && "$TRAVIS_BRANCH" = "master" && "$TRAVIS_PULL_REQUEST" = "false" ]]; then DO_UPLOAD="true"; else DO_UPLOAD="false"; fi
|
||||
|
||||
+1
-1
@@ -105,7 +105,7 @@ install:
|
||||
- pip freeze | sort
|
||||
|
||||
test_script:
|
||||
- nosetests tests/
|
||||
- nosetests
|
||||
- flake8 zipline tests
|
||||
|
||||
branches:
|
||||
|
||||
@@ -5,6 +5,8 @@ with-ignore-docstrings=1
|
||||
with-timer=1
|
||||
timer-top-n=15
|
||||
cover-package=zipline
|
||||
with-doctest=1
|
||||
testmatch=(?:^|[\\b_\\.-])[Tt]est(?!ing)
|
||||
|
||||
[metadata]
|
||||
description-file = README.rst
|
||||
|
||||
@@ -125,7 +125,7 @@ def to_dict(l):
|
||||
|
||||
Example
|
||||
-------
|
||||
>>> to_dict([2, 3, 4])
|
||||
>>> to_dict([2, 3, 4]) # doctest: +SKIP
|
||||
{'0': 2, '1': 3, '2': 4}
|
||||
"""
|
||||
return dict(zip(map(str, range(len(l))), l))
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2013 Quantopian, Inc.
|
||||
#
|
||||
@@ -1,91 +0,0 @@
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
import doctest
|
||||
from unittest import TestCase
|
||||
|
||||
from zipline import testing
|
||||
from zipline.lib import adjustment, normalize
|
||||
from zipline.pipeline import (
|
||||
engine,
|
||||
expression,
|
||||
)
|
||||
from zipline.utils import (
|
||||
cache,
|
||||
data,
|
||||
functional,
|
||||
input_validation,
|
||||
memoize,
|
||||
numpy_utils,
|
||||
preprocess,
|
||||
)
|
||||
|
||||
|
||||
class DoctestTestCase(TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
import pdb
|
||||
# Workaround for the issue addressed by this (unmerged) PR to pdbpp:
|
||||
# https://bitbucket.org/antocuni/pdb/pull-request/40/fix-ensure_file_can_write_unicode/diff # noqa
|
||||
if '_pdbpp_path_hack' in pdb.__file__:
|
||||
cls._skip = True
|
||||
else:
|
||||
cls._skip = False
|
||||
cls.flags = doctest.REPORT_CDIFF | doctest.IGNORE_EXCEPTION_DETAIL
|
||||
|
||||
def _check_docs(self, module):
|
||||
if self._skip:
|
||||
# Printing this directly to __stdout__ so that it doesn't get
|
||||
# captured by nose.
|
||||
print("Warning: Skipping doctests for %s because "
|
||||
"pdbpp is installed." % module.__name__, file=sys.__stdout__)
|
||||
return
|
||||
try:
|
||||
doctest.testmod(
|
||||
module,
|
||||
verbose=True,
|
||||
raise_on_error=True,
|
||||
optionflags=self.flags,
|
||||
)
|
||||
except doctest.UnexpectedException as e:
|
||||
raise e.exc_info[1]
|
||||
except doctest.DocTestFailure as e:
|
||||
print("Got:")
|
||||
print(e.got)
|
||||
raise
|
||||
|
||||
def test_adjustment_docs(self):
|
||||
self._check_docs(adjustment)
|
||||
|
||||
def test_expression_docs(self):
|
||||
self._check_docs(expression)
|
||||
|
||||
def test_engine_docs(self):
|
||||
self._check_docs(engine)
|
||||
|
||||
def test_memoize_docs(self):
|
||||
self._check_docs(memoize)
|
||||
|
||||
def test_testing_docs(self):
|
||||
self._check_docs(testing)
|
||||
|
||||
def test_preprocess_docs(self):
|
||||
self._check_docs(preprocess)
|
||||
|
||||
def test_input_validation_docs(self):
|
||||
self._check_docs(input_validation)
|
||||
|
||||
def test_cache_docs(self):
|
||||
self._check_docs(cache)
|
||||
|
||||
def test_numpy_utils_docs(self):
|
||||
self._check_docs(numpy_utils)
|
||||
|
||||
def test_data_docs(self):
|
||||
self._check_docs(data)
|
||||
|
||||
def test_functional_docs(self):
|
||||
self._check_docs(functional)
|
||||
|
||||
def test_normalize_docs(self):
|
||||
self._check_docs(normalize)
|
||||
@@ -122,7 +122,7 @@ def simplex_projection(v, b=1):
|
||||
|
||||
:Example:
|
||||
>>> proj = simplex_projection([.4 ,.3, -.4, .5])
|
||||
>>> print(proj)
|
||||
>>> proj # doctest: +NORMALIZE_WHITESPACE
|
||||
array([ 0.33333333, 0.23333333, 0. , 0.43333333])
|
||||
>>> print(proj.sum())
|
||||
1.0
|
||||
|
||||
@@ -226,7 +226,7 @@ class LabelArray(ndarray):
|
||||
|
||||
1. Someone tries to directly construct a new array by doing::
|
||||
|
||||
>>> ndarray.__new__(LabelArray, ...)
|
||||
>>> ndarray.__new__(LabelArray, ...) # doctest: +SKIP
|
||||
|
||||
In this case, obj will be None. We treat this as an error case and
|
||||
fail.
|
||||
|
||||
@@ -333,9 +333,9 @@ class Factor(RestrictedDTypeMixin, ComputableTerm):
|
||||
Factors. For example, constructing a Factor that computes the average of
|
||||
two other Factors is simply::
|
||||
|
||||
>>> f1 = SomeFactor(...)
|
||||
>>> f2 = SomeOtherFactor(...)
|
||||
>>> average = (f1 + f2) / 2.0
|
||||
>>> f1 = SomeFactor(...) # doctest: +SKIP
|
||||
>>> f2 = SomeOtherFactor(...) # doctest: +SKIP
|
||||
>>> average = (f1 + f2) / 2.0 # doctest: +SKIP
|
||||
|
||||
Factors can also be converted into :class:`zipline.pipeline.Filter` objects
|
||||
via comparison operators: (``<``, ``<=``, ``!=``, ``eq``, ``>``, ``>=``).
|
||||
@@ -492,8 +492,10 @@ class Factor(RestrictedDTypeMixin, ComputableTerm):
|
||||
to use the ``mask`` parameter to discard values at the extremes of the
|
||||
distribution::
|
||||
|
||||
>>> base = MyFactor(...)
|
||||
>>> normalized = base.demean(mask=base.percentile_between(1, 99))
|
||||
>>> base = MyFactor(...) # doctest: +SKIP
|
||||
>>> normalized = base.demean(
|
||||
... mask=base.percentile_between(1, 99),
|
||||
... ) # doctest: +SKIP
|
||||
|
||||
``demean()`` is only supported on Factors of dtype float64.
|
||||
|
||||
@@ -553,8 +555,10 @@ class Factor(RestrictedDTypeMixin, ComputableTerm):
|
||||
outliers, it is often useful to use the ``mask`` parameter to discard
|
||||
values at the extremes of the distribution::
|
||||
|
||||
>>> base = MyFactor(...)
|
||||
>>> normalized = base.zscore(mask=base.percentile_between(1, 99))
|
||||
>>> base = MyFactor(...) # doctest: +SKIP
|
||||
>>> normalized = base.zscore(
|
||||
... mask=base.percentile_between(1, 99),
|
||||
... ) # doctest: +SKIP
|
||||
|
||||
``zscore()`` is only supported on Factors of dtype float64.
|
||||
|
||||
|
||||
@@ -26,9 +26,9 @@ def delimit(delimiters, content):
|
||||
Surround `content` with the first and last characters of `delimiters`.
|
||||
|
||||
>>> delimit('[]', "foo")
|
||||
[foo]
|
||||
u'[foo]'
|
||||
>>> delimit('""', "foo")
|
||||
'"foo"'
|
||||
u'"foo"'
|
||||
"""
|
||||
if len(delimiters) != 2:
|
||||
raise ValueError(
|
||||
@@ -220,7 +220,7 @@ def format_attrs(attrs):
|
||||
|
||||
Example
|
||||
-------
|
||||
>>> format_attrs({'key1': 'value1', 'key2': 'value2'})
|
||||
>>> format_attrs({'key1': 'value1', 'key2': 'value2'}) # doctest: +SKIP
|
||||
'[key1=value1, key2=value2]'
|
||||
"""
|
||||
if not attrs:
|
||||
|
||||
@@ -210,7 +210,7 @@ def alias(attr_name):
|
||||
>>> class C(object):
|
||||
... attr = 1
|
||||
...
|
||||
>>> class D(object):
|
||||
>>> class D(C):
|
||||
... attr_alias = alias('attr')
|
||||
...
|
||||
>>> D.attr
|
||||
|
||||
@@ -41,7 +41,7 @@ class CallbackManager(object):
|
||||
>>> with manager('example'):
|
||||
... print('inside example block')
|
||||
entering example block
|
||||
inside example
|
||||
inside example block
|
||||
exiting example block
|
||||
|
||||
These are reusable with different args:
|
||||
|
||||
@@ -23,7 +23,7 @@ def invert(d):
|
||||
"""
|
||||
Invert a dictionary into a dictionary of sets.
|
||||
|
||||
>>> invert({'a': 1, 'b': 2, 'c': 1})
|
||||
>>> invert({'a': 1, 'b': 2, 'c': 1}) # doctest: +SKIP
|
||||
{1: {'a', 'c'}, 2: {'b'}}
|
||||
"""
|
||||
out = {}
|
||||
|
||||
@@ -302,7 +302,8 @@ class AfterOpen(StatelessRule):
|
||||
A rule that triggers for some offset after the market opens.
|
||||
Example that triggers after 30 minutes of the market opening:
|
||||
|
||||
>>> AfterOpen(minutes=30)
|
||||
>>> AfterOpen(minutes=30) # doctest: +ELLIPSIS
|
||||
<zipline.utils.events.AfterOpen object at ...>
|
||||
"""
|
||||
def __init__(self, offset=None, **kwargs):
|
||||
self.offset = _build_offset(
|
||||
@@ -346,7 +347,8 @@ class BeforeClose(StatelessRule):
|
||||
A rule that triggers for some offset time before the market closes.
|
||||
Example that triggers for the last 30 minutes every day:
|
||||
|
||||
>>> BeforeClose(minutes=30)
|
||||
>>> BeforeClose(minutes=30) # doctest: +ELLIPSIS
|
||||
<zipline.utils.events.BeforeClose object at ...>
|
||||
"""
|
||||
def __init__(self, offset=None, **kwargs):
|
||||
self.offset = _build_offset(
|
||||
|
||||
@@ -69,7 +69,7 @@ class final(with_metaclass(ABCMeta)):
|
||||
|
||||
Example usage:
|
||||
>>> from six import with_metaclass
|
||||
>>> class C(with_metaclass(FinalMeta)):
|
||||
>>> class C(with_metaclass(FinalMeta, object)):
|
||||
... @final
|
||||
... def f(self):
|
||||
... return 'value'
|
||||
|
||||
@@ -220,14 +220,16 @@ def unzip(seq, elem_len=None):
|
||||
>>> seq = [('a', 1), ('b', 2), ('c', 3, 'extra')]
|
||||
>>> cs, ns = unzip(seq)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
...
|
||||
ValueError: element at index 2 was length 3, expected 2
|
||||
|
||||
# allows an explicit element length instead of infering
|
||||
>>> seq = [('a', 1, 'extra'), ('b', 2), ('c', 3)]
|
||||
>>> cs, ns = unzip(seq, 2)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: element at index 0 was length 3, expected 2
|
||||
|
||||
# handles empty sequences when a length is given
|
||||
>>> cs, ns = unzip([], elem_len=2)
|
||||
>>> cs == ns == ()
|
||||
|
||||
@@ -216,10 +216,11 @@ def expect_dtypes(**named):
|
||||
...
|
||||
>>> foo(arange(3), 'foo')
|
||||
(array([0, 1, 2]), 'foo')
|
||||
>>> foo(arange(3, dtype=float), 'foo')
|
||||
>>> foo(arange(3, dtype=float), 'foo') # doctest: +NORMALIZE_WHITESPACE
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: foo() expected an argument with dtype 'int64' for argument 'x', but got dtype 'float64' instead. # noqa
|
||||
TypeError: zipline.utils.input_validation.foo() expected a value with
|
||||
dtype 'int64' for argument 'x', but got 'float64' instead.
|
||||
"""
|
||||
for name, type_ in iteritems(named):
|
||||
if not isinstance(type_, (dtype, tuple)):
|
||||
@@ -278,10 +279,11 @@ def expect_kinds(**named):
|
||||
2
|
||||
>>> foo(int32(2))
|
||||
2
|
||||
>>> foo(float32(2))
|
||||
>>> foo(float32(2)) # doctest: +NORMALIZE_WHITESPACE
|
||||
Traceback (most recent call last):
|
||||
...n
|
||||
TypeError: foo() expected a numpy object of kind 'i' for argument 'x', but got 'f' instead. # noqa
|
||||
...
|
||||
TypeError: zipline.utils.input_validation.foo() expected a numpy object of
|
||||
kind 'i' for argument 'x', but got 'f' instead.
|
||||
"""
|
||||
for name, kind in iteritems(named):
|
||||
if not isinstance(kind, (str, tuple)):
|
||||
@@ -337,10 +339,11 @@ def expect_types(*_pos, **named):
|
||||
...
|
||||
>>> foo(2, '3')
|
||||
(2, '3')
|
||||
>>> foo(2.0, '3')
|
||||
>>> foo(2.0, '3') # doctest: +NORMALIZE_WHITESPACE
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: foo() expected an argument of type 'int' for argument 'x', but got float instead. # noqa
|
||||
TypeError: zipline.utils.input_validation.foo() expected a value of type
|
||||
int for argument 'x', but got float instead.
|
||||
"""
|
||||
if _pos:
|
||||
raise TypeError("expect_types() only takes keyword arguments.")
|
||||
@@ -463,10 +466,11 @@ def expect_element(*_pos, **named):
|
||||
'A'
|
||||
>>> foo('b')
|
||||
'B'
|
||||
>>> foo('c')
|
||||
>>> foo('c') # doctest: +NORMALIZE_WHITESPACE
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: foo() expected a value in ('a', 'b') for argument 'x', but got 'c' instead. # noqa
|
||||
ValueError: zipline.utils.input_validation.foo() expected a value in
|
||||
('a', 'b') for argument 'x', but got 'c' instead.
|
||||
|
||||
Notes
|
||||
-----
|
||||
@@ -505,10 +509,11 @@ def expect_dimensions(**dimensions):
|
||||
...
|
||||
>>> foo(array([1, 1]), array([[1, 1], [2, 2]]))
|
||||
2
|
||||
>>> foo(array([1, 1], array([1, 1])))
|
||||
>>> foo(array([1, 1]), array([1, 1])) # doctest: +NORMALIZE_WHITESPACE
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: foo() expected a 2-D array for argument 'y', but got a 1-D array instead. # noqa
|
||||
ValueError: zipline.utils.input_validation.foo() expected a 2-D array for
|
||||
argument 'y', but got a 1-D array instead.
|
||||
"""
|
||||
def _expect_dimension(expected_ndim):
|
||||
def _check(func, argname, argvalue):
|
||||
|
||||
+15
-11
@@ -24,14 +24,15 @@ def compose_types(a, *cs):
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
class M(type):
|
||||
def __new__(mcls, name, bases, dict_):
|
||||
dict_['ayy'] = 'lmao'
|
||||
return super().__new__(mcls, name, bases, dict_)
|
||||
>>> class M(type):
|
||||
... def __new__(mcls, name, bases, dict_):
|
||||
... dict_['ayy'] = 'lmao'
|
||||
... return super(M, mcls).__new__(mcls, name, bases, dict_)
|
||||
|
||||
|
||||
class C(metaclass=M):
|
||||
pass
|
||||
>>> from six import with_metaclass
|
||||
>>> class C(with_metaclass(M, object)):
|
||||
... pass
|
||||
|
||||
|
||||
We now want to create a sublclass of ``C`` that is also an abstract class.
|
||||
@@ -43,10 +44,11 @@ def compose_types(a, *cs):
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
class D(C, metaclass=compose_types(M, ABCMeta)):
|
||||
@abstractmethod
|
||||
def f(self):
|
||||
raise NotImplementedError('f')
|
||||
>>> from abc import ABCMeta, abstractmethod
|
||||
>>> class D(with_metaclass(compose_types(M, ABCMeta), C)):
|
||||
... @abstractmethod
|
||||
... def f(self):
|
||||
... raise NotImplementedError('f')
|
||||
|
||||
|
||||
We can see that this class has both metaclasses applied to it:
|
||||
@@ -54,8 +56,10 @@ def compose_types(a, *cs):
|
||||
.. code-block:: python
|
||||
|
||||
>>> D.ayy
|
||||
lmao
|
||||
'lmao'
|
||||
>>> D()
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: Can't instantiate abstract class D with abstract methods f
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user