Merge pull request #1042 from quantopian/test-fixtures

TST: move test_utils and adds test fixture classes
This commit is contained in:
Joe Jevnik
2016-03-10 16:51:52 -05:00
34 changed files with 727 additions and 146 deletions
+12 -8
View File
@@ -16,20 +16,20 @@ None
Enhancements
~~~~~~~~~~~~
* Added new datasets
:class:`~zipline.pipeline.data.buyback_auth.CashBuybackAuthorizations`
* Added new datasets
:class:`~zipline.pipeline.data.buyback_auth.CashBuybackAuthorizations`
and :class:`~zipline.pipeline.data.buyback_auth.ShareBuybackAuthorizations`
for use in the Pipeline API. These datasets provide an abstract interface for
adding cash and share buyback authorizations data, respectively, to a new
algorithm. pandas-based reference implementations for these datasets can be found in
:mod:`zipline.pipeline.loaders.buyback_auth`, and experimental blaze-based
implementations can be found in
adding cash and share buyback authorizations data, respectively, to a new
algorithm. pandas-based reference implementations for these datasets can be
found in :mod:`zipline.pipeline.loaders.buyback_auth`, and experimental
blaze-based implementations can be found in
:mod:`zipline.pipeline.loaders.blaze.buyback_auth`. (:issue:`1022`).
* Added new built-in factors,
:class:`zipline.pipeline.factors.BusinessDaysSinceCashBuybackAuth` and
:class:`zipline.pipeline.factors.BusinessDaysSinceShareBuybackAuth`. These
factors use the new ``CashBuybackAuthorizations`` and
factors use the new ``CashBuybackAuthorizations`` and
``ShareBuybackAuthorizations`` datasets, respectively. (:issue:`1022`).
@@ -70,4 +70,8 @@ None
Miscellaneous
~~~~~~~~~~~~~
None
* Adds :class:`~zipline.testing.fixtures.ZiplineTestCase` which provides hooks
to consume test fixtures. Fixtures are things like:
:class:`~zipline.testing.fixtures.WithAssetFinder` which will make
``self.asset_finder`` available to your test with some mock data
(:issue:`1042`).
+1 -3
View File
@@ -39,9 +39,7 @@ from zipline.data.us_equity_pricing import (
)
from zipline.finance.trading import TradingEnvironment
from zipline.pipeline.data import USEquityPricing
from zipline.utils.test_utils import (
seconds_to_timestamp,
)
from zipline.testing import seconds_to_timestamp
TEST_CALENDAR_START = Timestamp('2015-06-01', tz='UTC')
TEST_CALENDAR_STOP = Timestamp('2015-06-30', tz='UTC')
+1 -1
View File
@@ -8,7 +8,7 @@ import numpy as np
from zipline.finance.trading import TradingEnvironment, noop_load
from zipline.history.history import HistorySpec
from zipline.protocol import BarData
from zipline.utils.test_utils import to_utc
from zipline.testing import to_utc
_cases_env = TradingEnvironment(load=noop_load)
+7 -6
View File
@@ -16,18 +16,19 @@ from zipline.pipeline import Pipeline
from zipline.pipeline.common import TS_FIELD_NAME
from zipline.pipeline.engine import SimplePipelineEngine
from zipline.pipeline.term import AssetExists
from zipline.utils.numpy_utils import (
NaTD,
make_datetime64D
)
from zipline.utils.pandas_utils import explode
from zipline.utils.test_utils import (
from zipline.testing import (
ExplodingObject,
gen_calendars,
make_simple_equity_info,
num_days_in_range,
tmp_asset_finder,
)
from zipline.utils.numpy_utils import (
NaTD,
make_datetime64D
)
from zipline.utils.pandas_utils import explode
from zipline.utils.tradingcalendar import trading_day
+1 -1
View File
@@ -22,6 +22,7 @@ from zipline.lib.adjustment import (
Float64Overwrite,
)
from zipline.lib.adjusted_array import AdjustedArray, NOMASK
from zipline.testing import check_arrays, parameter_space
from zipline.utils.numpy_utils import (
coerce_to_dtype,
datetime64ns_dtype,
@@ -29,7 +30,6 @@ from zipline.utils.numpy_utils import (
float64_dtype,
int64_dtype,
)
from zipline.utils.test_utils import check_arrays, parameter_space
def moving_window(array, nrows):
+1 -1
View File
@@ -38,7 +38,7 @@ from zipline.utils.numpy_utils import (
int64_dtype,
repeat_last_axis,
)
from zipline.utils.test_utils import (
from zipline.testing import (
tmp_asset_finder,
make_simple_equity_info,
)
+1 -3
View File
@@ -37,9 +37,7 @@ from zipline.pipeline.loaders.blaze import (
BlazeCashBuybackAuthorizationsLoader,
BlazeShareBuybackAuthorizationsLoader,
)
from zipline.utils.test_utils import (
tmp_asset_finder,
)
from zipline.testing import tmp_asset_finder
from .base import EventLoaderCommonMixin, DATE_FIELD_NAME
+1 -1
View File
@@ -9,7 +9,7 @@ from pandas.util.testing import assert_frame_equal
from zipline.pipeline import Pipeline
from zipline.pipeline.data.testing import TestingDataSet as TDS
from zipline.utils.test_utils import chrange, temp_pipeline_engine
from zipline.testing import chrange, temp_pipeline_engine
class LatestTestCase(TestCase):
+1 -1
View File
@@ -27,7 +27,7 @@ from zipline.pipeline.loaders.earnings import EarningsCalendarLoader
from zipline.pipeline.loaders.blaze import (
BlazeEarningsCalendarLoader,
)
from zipline.utils.test_utils import (
from zipline.testing import (
make_simple_equity_info,
tmp_asset_finder,
)
+2 -2
View File
@@ -62,13 +62,13 @@ from zipline.pipeline.factors import (
MaxDrawdown,
SimpleMovingAverage,
)
from zipline.utils.memoize import lazyval
from zipline.utils.test_utils import (
from zipline.testing import (
make_rotating_equity_info,
make_simple_equity_info,
product_upper_triangle,
check_arrays,
)
from zipline.utils.memoize import lazyval
class RollingSumDifference(CustomFactor):
+1 -1
View File
@@ -22,7 +22,7 @@ from zipline.pipeline.factors import (
Returns,
RSI,
)
from zipline.utils.test_utils import (
from zipline.testing import (
check_allclose,
check_arrays,
parameter_space,
+1 -2
View File
@@ -23,9 +23,8 @@ from numpy.random import randn, seed as random_seed
from zipline.errors import BadPercentileBounds
from zipline.pipeline import Filter, Factor, TermGraph
from zipline.utils.test_utils import check_arrays
from zipline.testing import check_arrays
from zipline.utils.numpy_utils import float64_dtype
from .base import BasePipelineTestCase, with_default_shape
+1 -2
View File
@@ -32,9 +32,8 @@ from zipline.pipeline.expression import (
NumericalExpression,
NUMEXPR_MATH_FUNCS,
)
from zipline.testing import check_arrays
from zipline.utils.numpy_utils import datetime64ns_dtype, float64_dtype
from zipline.utils.test_utils import check_arrays
class F(Factor):
+1 -1
View File
@@ -57,7 +57,7 @@ from zipline.pipeline.loaders.frame import DataFrameLoader
from zipline.pipeline.loaders.equity_pricing_loader import (
USEquityPricingLoader,
)
from zipline.utils.test_utils import (
from zipline.testing import (
make_simple_equity_info,
str_to_seconds,
)
@@ -54,7 +54,7 @@ from zipline.pipeline.loaders.equity_pricing_loader import (
from zipline.errors import WindowLengthTooLong
from zipline.finance.trading import TradingEnvironment
from zipline.pipeline.data import USEquityPricing
from zipline.utils.test_utils import (
from zipline.testing import (
seconds_to_timestamp,
str_to_seconds,
)
+24 -29
View File
@@ -25,19 +25,8 @@ import numpy as np
import pandas as pd
from contextlib2 import ExitStack
from zipline.algorithm import TradingAlgorithm
from zipline.api import FixedSlippage
from zipline.assets import Equity, Future
from zipline.utils.api_support import ZiplineAPI
from zipline.utils.control_flow import nullctx
from zipline.utils.test_utils import (
setup_logger,
teardown_logger,
make_trade_panel_for_asset_info,
parameter_space,
)
import zipline.utils.factory as factory
import zipline.utils.simfactory as simfactory
from zipline.errors import (
OrderDuringInitialize,
RegisterTradingControlPostInit,
@@ -47,6 +36,18 @@ from zipline.errors import (
RootSymbolNotFound,
UnsupportedDatetimeFormat,
)
from zipline.assets import Equity, Future
from zipline.finance.execution import LimitOrder
from zipline.finance.commission import PerShare
from zipline.finance.order import ORDER_STATUS
from zipline.finance.trading import SimulationParameters, TradingEnvironment
from zipline.protocol import DATASOURCE_TYPE
from zipline.sources import (
SpecificEquityTrades,
DataFrameSource,
DataPanelSource,
RandomWalkSource,
)
from zipline.test_algorithms import (
access_account_in_init,
access_portfolio_in_init,
@@ -85,30 +86,24 @@ from zipline.test_algorithms import (
record_float_magic,
record_variables,
)
from zipline.utils.context_tricks import CallbackManager
import zipline.utils.events
from zipline.utils.test_utils import (
from zipline.testing import (
assert_single_position,
drain_zipline,
make_jagged_equity_info,
tmp_asset_finder,
to_utc,
setup_logger,
teardown_logger,
make_trade_panel_for_asset_info,
parameter_space,
)
from zipline.sources import (SpecificEquityTrades,
DataFrameSource,
DataPanelSource,
RandomWalkSource)
from zipline.finance.execution import LimitOrder
from zipline.finance.trading import SimulationParameters
from zipline.finance.order import ORDER_STATUS
from zipline.utils.api_support import set_algo_instance
from zipline.utils.api_support import ZiplineAPI, set_algo_instance
from zipline.utils.context_tricks import CallbackManager
from zipline.utils.control_flow import nullctx
import zipline.utils.events
from zipline.utils.events import DateRuleFactory, TimeRuleFactory, Always
from zipline.algorithm import TradingAlgorithm
from zipline.protocol import DATASOURCE_TYPE
from zipline.finance.trading import TradingEnvironment
from zipline.finance.commission import PerShare
import zipline.utils.factory as factory
import zipline.utils.simfactory as simfactory
from zipline.utils.tradingcalendar import trading_day, trading_days
# Because test cases appear to reuse some resources.
+8 -7
View File
@@ -26,16 +26,17 @@ import pytz
from zipline.finance import trading
from zipline.algorithm import TradingAlgorithm
from zipline.finance import slippage
from zipline.utils import factory
from zipline.utils.factory import create_simulation_parameters
from zipline.utils.test_utils import (
from zipline.protocol import (
Event,
DATASOURCE_TYPE,
)
from zipline.testing import (
setup_logger,
teardown_logger
)
from zipline.protocol import (
Event,
DATASOURCE_TYPE
)
from zipline.utils import factory
from zipline.utils.factory import create_simulation_parameters
DEFAULT_TIMEOUT = 15 # seconds
EXTENDED_TIMEOUT = 90
+1 -1
View File
@@ -72,7 +72,7 @@ from zipline.errors import (
AssetDBImpossibleDowngrade,
)
from zipline.finance.trading import TradingEnvironment, noop_load
from zipline.utils.test_utils import (
from zipline.testing import (
all_subindices,
make_commodity_future_info,
make_rotating_equity_info,
+12 -15
View File
@@ -14,28 +14,25 @@
# limitations under the License.
from collections import deque
from copy import deepcopy
from datetime import datetime
from unittest import TestCase
import pytz
import numpy as np
import pandas as pd
from datetime import datetime
from unittest import TestCase
from zipline.utils.test_utils import setup_logger, teardown_logger
from zipline.sources.data_source import DataSource
import zipline.utils.factory as factory
from zipline.transforms import batch_transform
from zipline.test_algorithms import (BatchTransformAlgorithm,
BatchTransformAlgorithmMinute)
from zipline.finance.trading import TradingEnvironment
from zipline.algorithm import TradingAlgorithm
from zipline.finance.trading import TradingEnvironment
from zipline.sources.data_source import DataSource
from zipline.test_algorithms import (
BatchTransformAlgorithm,
BatchTransformAlgorithmMinute,
)
from zipline.testing import setup_logger, teardown_logger
from zipline.transforms import batch_transform
import zipline.utils.factory as factory
from zipline.utils.tradingcalendar import trading_days
from copy import deepcopy
@batch_transform
+1 -1
View File
@@ -28,7 +28,7 @@ from zipline.finance.execution import (
)
from zipline.sources.test_source import create_trade
from zipline.utils.test_utils import(
from zipline.testing import(
setup_logger,
teardown_logger,
)
+3 -3
View File
@@ -3,6 +3,7 @@ import sys
import doctest
from unittest import TestCase
from zipline import testing
from zipline.lib import adjustment
from zipline.pipeline import (
engine,
@@ -16,7 +17,6 @@ from zipline.utils import (
memoize,
numpy_utils,
preprocess,
test_utils,
)
@@ -66,8 +66,8 @@ class DoctestTestCase(TestCase):
def test_memoize_docs(self):
self._check_docs(memoize)
def test_test_utils_docs(self):
self._check_docs(test_utils)
def test_testing_docs(self):
self._check_docs(testing)
def test_preprocess_docs(self):
self._check_docs(preprocess)
+5 -8
View File
@@ -15,24 +15,21 @@
from unittest import TestCase
import zipline.utils.simfactory as simfactory
import zipline.utils.factory as factory
from zipline.finance.slippage import FixedSlippage
from zipline.finance.trading import TradingEnvironment
from zipline.test_algorithms import (
ExceptionAlgorithm,
DivByZeroAlgorithm,
SetPortfolioAlgorithm,
)
from zipline.finance.slippage import FixedSlippage
from zipline.finance.trading import TradingEnvironment
from zipline.utils.test_utils import (
from zipline.testing import (
drain_zipline,
setup_logger,
teardown_logger,
ExceptionSource,
)
import zipline.utils.simfactory as simfactory
import zipline.utils.factory as factory
DEFAULT_TIMEOUT = 15 # seconds
EXTENDED_TIMEOUT = 90
+6 -7
View File
@@ -15,9 +15,13 @@
from unittest import TestCase
from nose_parameterized import parameterized
from six.moves import range
from nose_parameterized import parameterized
from zipline.errors import(
BadOrderParameters
)
from zipline.finance.execution import (
LimitOrder,
@@ -25,16 +29,11 @@ from zipline.finance.execution import (
StopLimitOrder,
StopOrder,
)
from zipline.utils.test_utils import(
from zipline.testing import(
setup_logger,
teardown_logger,
)
from zipline.errors import(
BadOrderParameters
)
class ExecutionStyleTestCase(TestCase):
"""
+13 -20
View File
@@ -16,40 +16,33 @@
"""
Tests for the zipline.finance package
"""
from datetime import datetime, timedelta
import itertools
import operator
import pytz
from unittest import TestCase
from datetime import datetime, timedelta
import numpy as np
import pandas as pd
from nose.tools import timed
import numpy as np
import pandas as pd
import pytz
from six.moves import range
from zipline.finance.blotter import Blotter
from zipline.finance.execution import MarketOrder, LimitOrder
from zipline.finance.trading import TradingEnvironment
from zipline.finance.performance import PerformanceTracker
from zipline.finance.trading import SimulationParameters
from zipline.gens.composites import date_sorted_sources
import zipline.protocol
from zipline.protocol import Event, DATASOURCE_TYPE
import zipline.utils.factory as factory
import zipline.utils.simfactory as simfactory
from zipline.finance.blotter import Blotter
from zipline.gens.composites import date_sorted_sources
from zipline.finance.trading import TradingEnvironment
from zipline.finance.execution import MarketOrder, LimitOrder
from zipline.finance.trading import SimulationParameters
from zipline.finance.performance import PerformanceTracker
from zipline.utils.test_utils import(
from zipline.testing import(
setup_logger,
teardown_logger,
assert_single_position
)
import zipline.utils.factory as factory
import zipline.utils.simfactory as simfactory
DEFAULT_TIMEOUT = 15 # seconds
EXTENDED_TIMEOUT = 90
+1 -1
View File
@@ -38,8 +38,8 @@ from zipline.history import history
from zipline.history.history_container import HistoryContainer
from zipline.protocol import BarData
from zipline.sources import RandomWalkSource, DataFrameSource
from zipline.testing import subtest
import zipline.utils.factory as factory
from zipline.utils.test_utils import subtest
class TestHistoryContainer(TestCase):
+10 -4
View File
@@ -5,13 +5,19 @@ from unittest import TestCase
from zipline.algorithm import TradingAlgorithm
from zipline.errors import TradingControlViolation
from zipline.sources import SpecificEquityTrades
from zipline.finance.trading import TradingEnvironment
from zipline.utils.test_utils import (
setup_logger, teardown_logger, security_list_copy, add_security_data,)
from zipline.sources import SpecificEquityTrades
from zipline.testing import (
add_security_data,
security_list_copy,
setup_logger,
teardown_logger,
)
from zipline.utils import factory
from zipline.utils.security_list import (
SecurityListSet, load_from_directory)
SecurityListSet,
load_from_directory,
)
LEVERAGED_ETFS = load_from_directory('leveraged_etf_list')
@@ -3,7 +3,8 @@ Tests for our testing utilities.
"""
from itertools import product
from unittest import TestCase
from zipline.utils.test_utils import parameter_space
from zipline.testing import parameter_space
class TestParameterSpace(TestCase):
+6 -10
View File
@@ -12,23 +12,19 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import pytz
import numpy as np
import pandas as pd
import talib
from datetime import timedelta, datetime
from unittest import TestCase, skip
from zipline.utils.test_utils import setup_logger, teardown_logger
import numpy as np
import pandas as pd
import pytz
import talib
import zipline.utils.factory as factory
from zipline.finance.trading import TradingEnvironment
from zipline.test_algorithms import TALIBAlgorithm
from zipline.testing import setup_logger, teardown_logger
import zipline.transforms.ta as ta
import zipline.utils.factory as factory
class TestTALIB(TestCase):
+1 -1
View File
@@ -25,6 +25,7 @@ from six import iteritems
from six.moves import range, map
from zipline.finance.trading import TradingEnvironment
from zipline.testing import subtest
import zipline.utils.events
from zipline.utils.events import (
EventRule,
@@ -49,7 +50,6 @@ from zipline.utils.events import (
MAX_MONTH_RANGE,
MAX_WEEK_RANGE,
)
from zipline.utils.test_utils import subtest
# A day known to be a half day.
+264
View File
@@ -0,0 +1,264 @@
from abc import abstractmethod, ABCMeta
from unittest import TestCase
from six import with_metaclass
from zipline.utils.final import (
FinalMeta,
final_meta_factory,
final,
)
class FinalMetaTestCase(TestCase):
@classmethod
def setUpClass(cls):
class ClassWithFinal(with_metaclass(FinalMeta, object)):
a = final('ClassWithFinal: a')
b = 'ClassWithFinal: b'
@final
def f(self):
return 'ClassWithFinal: f'
def g(self):
return 'ClassWithFinal: g'
cls.class_ = ClassWithFinal
def test_subclass_no_override(self):
"""
Tests that it is valid to create a subclass that does not override
any methods.
"""
class SubClass(self.class_):
pass
def test_subclass_no_final_override(self):
"""
Tests that it is valid to create a subclass that does not override
and final methods.
"""
class SubClass(self.class_):
b = 'SubClass: b'
def g(self):
return 'SubClass: g'
def test_override_final_no_decorator(self):
"""
Tests that attempting to create a subclass that overrides a final
method will raise a `TypeError`.
"""
with self.assertRaises(TypeError):
class SubClass(self.class_):
def f(self):
return 'SubClass: f'
def test_override_final_attribute(self):
"""
Tests that attempting to create a subclass that overrides a final
attribute will raise a `TypeError`.
"""
with self.assertRaises(TypeError):
class SubClass(self.class_):
a = 'SubClass: a'
def test_override_final_with_decorator(self):
"""
Tests that attempting to create a subclass that overrides a final
method will raise a `TypeError` even if you mark the new version as
final.
"""
with self.assertRaises(TypeError):
class SubClass(self.class_):
@final
def f(self):
return 'SubClass: f'
def test_override_final_attribute_with_final(self):
"""
Tests that attempting to create a subclass that overrides a final
attribute will raise a `TypeError` even if you mark the new version as
final.
"""
with self.assertRaises(TypeError):
class SubClass(self.class_):
a = final('SubClass: a')
def test_override_on_class_object(self):
"""
Tests overriding final methods and attributes on the class object
itself.
"""
class SubClass(self.class_):
pass
with self.assertRaises(TypeError):
SubClass.f = lambda self: 'SubClass: f'
with self.assertRaises(TypeError):
SubClass.a = 'SubClass: a'
def test_override_on_instance(self):
"""
Tests overriding final methods on instances of a class.
"""
class SubClass(self.class_):
def h(self):
pass
s = SubClass()
with self.assertRaises(TypeError):
s.f = lambda self: 'SubClass: f'
with self.assertRaises(TypeError):
s.a = lambda self: 'SubClass: a'
def test_override_on_super(self):
"""
Tests overriding on the class that has the @final methods in it.
"""
old_a = self.class_.a
old_f = self.class_.f
try:
with self.assertRaises(TypeError):
self.class_.f = lambda *args: None
except Exception:
self.class_.f = old_f
raise
try:
with self.assertRaises(TypeError):
self.class_.a = 'SubClass: a'
except Exception:
self.class_.a = old_a
raise
def test_override___setattr___on_subclass(self):
"""
Tests an attempt to override __setattr__ which is implicitly final.
"""
with self.assertRaises(TypeError):
class SubClass(self.class_):
def __setattr__(self, name, value):
object.__setattr__(self, name, value)
def test_override___setattr___on_instance(self):
"""
Tests overriding __setattr__ on an instance.
"""
class SubClass(self.class_):
pass
s = SubClass()
with self.assertRaises(TypeError):
s.__setattr__ = lambda a, b: None
class FinalABCMetaTestCase(FinalMetaTestCase):
@classmethod
def setUpClass(cls):
FinalABCMeta = final_meta_factory(ABCMeta)
class ABCWithFinal(with_metaclass(FinalABCMeta, object)):
a = final('ABCWithFinal: a')
b = 'ABCWithFinal: b'
@final
def f(self):
return 'ABCWithFinal: f'
def g(self):
return 'ABCWithFinal: g'
@abstractmethod
def h(self):
raise NotImplementedError('h')
cls.class_ = ABCWithFinal
def test_cannot_instantiate_subclass(self):
"""
Tests that you cannot create an instance of a subclass
that does not implement the abstractmethod h.
"""
class AbstractSubClass(self.class_):
pass
with self.assertRaises(TypeError):
AbstractSubClass()
def test_override_on_instance(self):
class SubClass(self.class_):
def h(self):
"""
Pass the abstract tests by creating this method.
"""
pass
s = SubClass()
with self.assertRaises(TypeError):
s.f = lambda self: 'SubClass: f'
def test_override___setattr___on_instance(self):
"""
Tests overriding __setattr__ on an instance.
"""
class SubClass(self.class_):
def h(self):
pass
s = SubClass()
with self.assertRaises(TypeError):
s.__setattr__ = lambda a, b: None
def test_subclass_setattr(self):
"""
Tests that subclasses don't destroy the __setattr__.
"""
class ClassWithFinal(with_metaclass(FinalMeta, object)):
@final
def f(self):
return 'ClassWithFinal: f'
class SubClass(ClassWithFinal):
def __init__(self):
self.a = 'a'
SubClass()
self.assertEqual(SubClass().a, 'a')
self.assertEqual(SubClass().f(), 'ClassWithFinal: f')
def test_final_classmethod(self):
class ClassWithClassMethod(with_metaclass(FinalMeta, object)):
count = 0
@final
@classmethod
def f(cls):
cls.count += 1
return cls.count
with self.assertRaises(TypeError):
class ClassOverridingClassMethod(ClassWithClassMethod):
@classmethod
def f(cls):
return "Oh Noes!"
with self.assertRaises(TypeError):
ClassWithClassMethod.f = lambda cls: 0
self.assertEqual(ClassWithClassMethod.f(), 1)
self.assertEqual(ClassWithClassMethod.f(), 2)
self.assertEqual(ClassWithClassMethod.f(), 3)
instance = ClassWithClassMethod()
with self.assertRaises(TypeError):
instance.f = lambda cls: 0
self.assertEqual(ClassWithClassMethod.f(), 4)
self.assertEqual(ClassWithClassMethod.f(), 5)
self.assertEqual(ClassWithClassMethod.f(), 6)
+37
View File
@@ -0,0 +1,37 @@
from .core import ( # noqa
EPOCH,
ExceptionSource,
ExplodingObject,
add_security_data,
all_pairs_matching_predicate,
all_subindices,
assert_single_position,
assert_timestamp_equal,
check_allclose,
check_arrays,
chrange,
drain_zipline,
gen_calendars,
make_commodity_future_info,
make_future_info,
make_jagged_equity_info,
make_rotating_equity_info,
make_simple_equity_info,
make_test_handler,
make_trade_panel_for_asset_info,
num_days_in_range,
parameter_space,
powerset,
product_upper_triangle,
seconds_to_timestamp,
security_list_copy,
setup_logger,
str_to_seconds,
subtest,
teardown_logger,
temp_pipeline_engine,
tmp_asset_finder,
tmp_assets_db,
to_series,
to_utc,
)
@@ -210,7 +210,7 @@ def all_pairs_matching_predicate(values, pred):
Examples
--------
>>> from zipline.utils.test_utils import all_pairs_matching_predicate
>>> from zipline.testing import all_pairs_matching_predicate
>>> from operator import eq, lt
>>> list(all_pairs_matching_predicate(range(5), eq))
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)]
@@ -665,7 +665,7 @@ def subtest(iterator, *_names):
"""
Construct a subtest in a unittest.
Consider using ``zipline.utils.test_utils.parameter_space`` when subtests
Consider using ``zipline.testing.parameter_space`` when subtests
are constructed over a single input or over the cross-product of multiple
inputs.
@@ -718,7 +718,7 @@ def subtest(iterator, *_names):
See Also
--------
zipline.utils.test_utils.parameter_space
zipline.testing.parameter_space
"""
def dec(f):
@wraps(f)
@@ -848,7 +848,7 @@ def parameter_space(**params):
See Also
--------
zipline.utils.test_utils.subtest
zipline.testing.subtest
"""
def decorator(f):
+158
View File
@@ -0,0 +1,158 @@
from unittest import TestCase
from contextlib2 import ExitStack
import pandas as pd
from six import with_metaclass
from .core import tmp_asset_finder
from ..utils import tradingcalendar
from ..utils.final import FinalMeta, final
class ZiplineTestCase(with_metaclass(FinalMeta, TestCase)):
"""
Shared extensions to core unittest.TestCase.
Overrides the default unittest setUp/tearDown functions with versions that
use ExitStack to correctly clean up resources, even in the face of
exceptions that occur during setUp/setUpClass.
Subclasses **should not override setUp or setUpClass**!
Instead, they should implement `init_instance_fixtures` for per-test-method
resources, and `init_class_fixtures` for per-class resources.
Resources that need to be cleaned up should be registered using
either `enter_{class,instance}_context` or `add_{class,instance}_callback}.
"""
@final
@classmethod
def setUpClass(cls):
cls._class_teardown_stack = ExitStack()
try:
cls._base_init_fixtures_was_called = False
cls.init_class_fixtures()
assert cls._base_init_fixtures_was_called, (
"ZiplineTestCase.init_class_fixtures() was not called.\n"
"This probably means that you overrode init_class_fixtures"
" without calling super()."
)
except:
cls.tearDownClass()
raise
@classmethod
def init_class_fixtures(cls):
"""
Override and implement this classmethod to register resources that
should be created and/or torn down on a per-class basis.
Subclass implementations of this should always invoke this with super()
to ensure that fixture mixins work properly.
"""
cls._base_init_fixtures_was_called = True
@final
@classmethod
def tearDownClass(cls):
cls._class_teardown_stack.close()
@final
@classmethod
def enter_class_context(cls, context_manager):
"""
Enter a context manager to be exited during the tearDownClass
"""
return cls._class_teardown_stack.enter_context(context_manager)
@final
@classmethod
def add_class_callback(cls, callback):
"""
Register a callback to be executed during tearDownClass.
"""
return cls._class_teardown_stack.callback(callback)
@final
def setUp(self):
self._instance_teardown_stack = ExitStack()
try:
self._init_instance_fixtures_was_called = False
self.init_instance_fixtures()
assert self._init_instance_fixtures_was_called, (
"ZiplineTestCase.init_instance_fixtures() was not"
" called.\n"
"This probably means that you overrode"
" init_instance_fixtures without calling super()."
)
except:
self.tearDown()
raise
def init_instance_fixtures(self):
self._init_instance_fixtures_was_called = True
@final
def tearDown(self):
self._instance_teardown_stack.close()
@final
def enter_instance_context(self, context_manager):
"""
Enter a context manager that should be exited during tearDown.
"""
return self._instance_teardown_stack.enter_context(context_manager)
@final
def add_instance_callback(self, callback):
"""
Register a callback to be executed during tearDown.
"""
return self._instance_teardown_stack.callback(callback)
class WithAssetFinder(object):
"""
ZiplineTestCase mixin providing cls.asset_finder as a class-level fixture.
After init_class_fixtures has been called, `cls.asset_finder` is populated
with an AssetFinder. The default finder just a `tmp_asset_finder`
This behavior can be altered by overriding `make_asset_finder` as a class
method.
"""
@classmethod
def make_asset_finder(cls):
return cls.enter_class_context(tmp_asset_finder())
@classmethod
def init_class_fixtures(cls):
super(WithAssetFinder, cls).init_class_fixtures()
cls.asset_finder = cls.make_asset_finder()
class WithNYSETradingDays(object):
"""
ZiplineTestCase mixin providing cls.trading_days as a class-level fixture.
After init_class_fixtures has been called, `cls.trading_days` is populated
with a DatetimeIndex containing NYSE calendar trading days ranging from:
(DATA_MAX_DAY - (cls.TRADING_DAY_COUNT) -> DATA_MAX_DAY)
The default value of TRADING_DAY_COUNT is 126 (half a trading-year).
Inheritors can override TRADING_DAY_COUNT to request more or less data.
"""
DATA_MAX_DAY = pd.Timestamp('2015-01-02')
TRADING_DAY_COUNT = 126
@classmethod
def init_class_fixtures(cls):
super(WithNYSETradingDays, cls).init_class_fixtures()
all_days = tradingcalendar.trading_days
end_loc = all_days.get_loc(cls.DATA_MAX_DAY)
start_loc = end_loc - cls.TRADING_DAY_COUNT
cls.trading_days = all_days[start_loc:end_loc + 1]
+138
View File
@@ -0,0 +1,138 @@
from abc import ABCMeta, abstractmethod
from weakref import WeakKeyDictionary
from six import with_metaclass, iteritems
from toolz import memoize
# Consistent error to be thrown in various cases regarding overriding
# `final` attributes.
_type_error = TypeError('Cannot override final attribute')
def bases_mro(bases):
"""
Yield classes in the order that methods should be looked up from the
base classes of an object.
"""
for base in bases:
for class_ in base.__mro__:
yield class_
def is_final(name, mro):
"""
Checks if `name` is a `final` object in the given `mro`.
We need to check the mro because we need to directly go into the __dict__
of the classes. Because `final` objects are descriptor, we need to grab
them _BEFORE_ the `__call__` is invoked.
"""
return any(isinstance(getattr(c, '__dict__', {}).get(name), final)
for c in bases_mro(mro))
@memoize(cache=WeakKeyDictionary())
def final_meta_factory(base):
"""
Creates a metaclass that inherits from `base` that also checks for `final`
attributes.
This will cause class construction to fail if the class attempts to
override a final method or attribute.
"""
class _FinalMeta(base):
def __new__(mcls, name, bases, dict_):
for k, v in iteritems(dict_):
if is_final(k, bases):
raise _type_error
setattr_ = dict_.get('__setattr__')
if setattr_ is None:
# No `__setattr__` was explicitly defined, look up the super
# class's. `bases[0]` will have a `__setattr__` because
# `object` does so we don't need to worry about the mro.
setattr_ = bases[0].__setattr__
if not is_final('__setattr__', bases) \
and not isinstance(setattr_, final):
# implicitly make the `__setattr__` a `final` object so that
# users cannot just avoid the descriptor protocol.
dict_['__setattr__'] = final(setattr_)
return base.__new__(mcls, name, bases, dict_)
def __setattr__(self, name, value):
"""
This stops the `final` attributes from being reassigned on the
class object.
"""
if is_final(name, self.__mro__):
raise _type_error
base.__setattr__(self, name, value)
_FinalMeta.__name__ = '%sFinalMeta' % base.__name__
return _FinalMeta
FinalMeta = final_meta_factory(type)
class final(with_metaclass(ABCMeta)):
"""
An attribute that cannot be overridden.
This is like the final modifier in Java.
Example usage:
>>> from six import with_metaclass
>>> class C(with_metaclass(FinalMeta)):
... @final
... def f(self):
... return 'value'
...
This constructs a class with final method `f`. This cannot be overridden
on the class object or on any instance. You cannot override this by
subclassing `C`; attempting to do so will raise a `TypeError` at class
construction time.
"""
def __new__(cls, attr):
# Decide if this is a method wrapper or an attribute wrapper.
# We are going to cache the `callable` check by creating a
# method or attribute wrapper.
if hasattr(attr, '__get__'):
return object.__new__(finaldescriptor)
else:
return object.__new__(finalvalue)
def __init__(self, attr):
self._attr = attr
def __set__(self, instance, value):
"""
`final` objects cannot be reassigned. This is the most import concept
about `final`s.
Unlike a `property` object, this will raise a `TypeError` when you
attempt to reassign it.
"""
raise _type_error
@abstractmethod
def __get__(self, instance, owner):
raise NotImplementedError('__get__')
class finalvalue(final):
"""
A wrapper for a non-descriptor attribute.
"""
def __get__(self, instance, owner):
return self._attr
class finaldescriptor(final):
"""
A final wrapper around a descriptor.
"""
def __get__(self, instance, owner):
return self._attr.__get__(instance, owner)