mirror of
https://github.com/wassname/catalyst.git
synced 2026-06-29 21:58:27 +08:00
bc0b117dc9
Changes BcolzDailyBarWriter to not be an abc, data is passed as an iterator of (sid, dataframe) pairs to the write method. Changes the AssetsDBWriter to be a single class which accepts an engine at construction time and has a `write` method for writing dataframes for the various tables. We no longer support writing the various other data types, callers should coerce their data into a dataframe themselves. See zipline.assets.synthetic for some helpers to do this. Adds many new fixtures and updates some existing fixtures to use the new ones: WithDefaultDateBounds A fixture that provides the suite a START_DATE and END_DATE. This is meant to make it easy for other fixtures to synchronize their date ranges without depending on eachother in strange ways. For example, WithBcolzMinuteBarReader and WithBcolzDailyBarReader by default should both have data for the same dates, so they may use depend on WithDefaultDates without forcing a dependency between them. WithTmpDir, WithInstanceTmpDir Provides the suite or individual test case a temporary directory. WithBcolzDailyBarReader Provides the suite a BcolzDailyBarReader which reads from bcolz data written to a temporary directory. The data will be read from dataframes and then converted to bcolz files with BcolzDailyBarWriter.write WithBcolzDailyBarReaderFromCSVs Provides the suite a BcolzDailyBarReader which reads from bcolz data written to a temporary directory. The data will be read from a collection of CSV files and then converted into the bcolz data through BcolzDailyBarWriter.write_csvs WithBcolzMinuteBarReader Provides the suite a BcolzMinuteBarReader which reads from bcolz data written to a temporary directory. The data will be read from dataframes and then converted to bcolz files with BcolzMinuteBarWriter.write WithAdjustmentReader Provides the suite a SQLiteAdjustmentReader which reads from an in memory sqlite database. The data will be read from dataframes and then converted into sqlite with SQLiteAdjustmentWriter.write WithDataPortal Provides each test case a DataPortal object with data from temporary resources.
124 lines
3.8 KiB
Python
124 lines
3.8 KiB
Python
from abc import ABCMeta, abstractmethod
|
|
|
|
from six import with_metaclass, iteritems
|
|
|
|
# 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))
|
|
|
|
|
|
class FinalMeta(type):
|
|
"""A metaclass template for classes the want to prevent subclassess from
|
|
overriding a some methods or attributes.
|
|
"""
|
|
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 super(FinalMeta, mcls).__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
|
|
|
|
super(FinalMeta, self).__setattr__(name, value)
|
|
|
|
|
|
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)
|