Repository: quantopian/zipline
File: zipline/lib/adjusted_array.py (Python)

Code before:
    """
    __slots__ = (
        '_data',
        '_view_kwargs',
        'adjustments',
        'missing_value',
        '__weakref__',
    )

    def __init__(self, data, adjustments, missing_value):
        self._data, self._view_kwargs = _normalize_array(data, missing_value)

        self.adjustments = adjustments
        self.missing_value = missing_value

    def append_adjustments(self, adjustments_to_append, append_back):
        """
        Adds ``adjustments_to_append`` to existing adjustments, handling
        index collisions according to ``append_back``.

        Parameters
        ----------
        adjustments_to_append : dict[int -> list[Adjustment]]
            The mapping of row indices to lists of adjustments that should be
            appended to existing adjustments.
        append_back : bool
            If `True` collisions will be resolved by appending new adjustment
            list at the end of existing adjustments. They will be appended at
            the front otherwise.
        """
        self.adjustments = merge_with(
            partial(self._merge_adjustments, append_back=append_back),
            self.adjustments,
            adjustments_to_append,
        )

    def _merge_adjustments(self, adjustment_lists, append_back):
        """
        Handles index collisions when merging adjustments.

        Notes
        -----
        ``adjustment_lists`` will contain at most two lists of adjustments (in
        case of index collision), and at least one (no collision).
        """
        if len(adjustment_lists) == 1:
            return adjustment_lists[0]
        elif append_back:
            adjustment_lists[0].extend(adjustment_lists[1])
            return adjustment_lists[0]
        else:

Review comment (suggestion):
Related to the note above, `append_back` reads slightly off to me. One option would be to call this `append` and have `append=False` mean "prepend", though that's somewhat confusing b/c it could be read as "don't append at all". Another option might do something like `np.searchsorted` and have `side='front'` or `side='back'`.

Code after:
        List(s) of new and/or existing adjustments for a given index.
    front_idx : int
        Index of list in ``adjustment_lists`` that should be used as baseline
        in case of a collision.
    back_idx : int
        Index of list in ``adjustment_lists`` that should extend baseline list
        in case of a collision.

    Returns
    -------
    adjustments : list[Adjustment]
        List of merged adjustments for a given index.
    """
    if len(adjustment_lists) == 1:
        return list(adjustment_lists[0])
    else:
        return adjustment_lists[front_idx] + adjustment_lists[back_idx]


_merge_methods = {
    'append': partial(_merge_simple, front_idx=0, back_idx=1),
    'prepend': partial(_merge_simple, front_idx=1, back_idx=0),
}


class AdjustedArray(object):
    """
    An array that can be iterated with a variable-length window, and which can
    provide different views on data from different perspectives.

    Parameters
    ----------
    data : np.ndarray
        The baseline data values.
    adjustments : dict[int -> list[Adjustment]]
        A dict mapping row indices to lists of adjustments to apply when we
        reach that row.
    missing_value : object
        A value to use to fill missing data in yielded windows.
        Should be a value coercible to `data.dtype`.
    """
    __slots__ = (
        '_data',
        '_view_kwargs',
        'adjustments',
        'missing_value',
        '__weakref__',
    )

    def __init__(self, data, adjustments, missing_value):
        self._data, self._view_kwargs = _normalize_array(data, missing_value)