Beispiel #1
0
 def _entries_in_inclusive_range(self, entries, begin_date=None, end_date=None):
     """
     Returns the list of entries satisfying begin_date <= date <= end_date.
     """
     get_date = lambda x: x.date
     if begin_date is None:
         begin_index = 0
     else:
         begin_index = bisect_key.bisect_left_with_key(entries, begin_date, key=get_date)
     if end_date is None:
         end_index = len(entries)
     else:
         end_index = bisect_key.bisect_left_with_key(entries, end_date+timedelta(days=1), key=get_date)
     return entries[begin_index:end_index]
Beispiel #2
0
def split_rows(rows, file_period):
    date_first = rows[0][0]
    date_last = rows[-1][0]
    date_end = date_first + file_period
    while date_end < date_last:
        index_end = bisect_left_with_key(rows,
                                         date_end,
                                         key=lambda row: row.date)
        date_begin = date_end - file_period
        index_begin = bisect_left_with_key(rows,
                                           date_begin,
                                           key=lambda row: row.date)
        yield date_end, rows[index_begin:index_end]
        report_interval = datetime.timedelta(days=random.randint(60, 80))
        date_end += report_interval
Beispiel #3
0
def iter_entry_dates(entries, date_begin, date_end):
    """Iterate over the entries in a date window.

    Args:
      entries: A date-sorted list of dated directives.
      date_begin: A datetime.date instance, the first date to include.
      date_end: A datetime.date instance, one day beyond the last date.
    Yields:
      Instances of the dated directives, between the dates, and in the order in
      which they appear.
    """
    getdate = lambda entry: entry.date
    index_begin = bisect_left_with_key(entries, date_begin, key=getdate)
    index_end = bisect_left_with_key(entries, date_end, key=getdate)
    for index in range(index_begin, index_end):
        yield entries[index]
Beispiel #4
0
def conversions(entries, conversion_account, conversion_currency, date=None):
    """Insert a conversion entry at date 'date' at the given account.

    Args:
      entries: A list of entries.
      conversion_account: A string, the account to book against.
      conversion_currency: A string, the transfer currency to use for zero prices
        on the conversion entry.
      date: The date before which to insert the conversion entry. The new
        entry will be inserted as the last entry of the date just previous
        to this date.
    Returns:
      A modified list of entries.
    """
    # Compute the balance at the given date.
    conversion_balance = interpolate.compute_entries_balance(entries,
                                                             date=date)

    # Early exit if there is nothing to do.
    conversion_cost_balance = conversion_balance.reduce(convert.get_cost)
    if conversion_cost_balance.is_empty():
        return entries

    # Calculate the index and the date for the new entry. We want to store it as
    # the last transaction of the day before.
    if date is not None:
        index = bisect_key.bisect_left_with_key(entries,
                                                date,
                                                key=lambda entry: entry.date)
        last_date = date - datetime.timedelta(days=1)
    else:
        index = len(entries)
        last_date = entries[-1].date

    meta = data.new_metadata('<conversions>', -1)
    narration = 'Conversion for {}'.format(conversion_balance)
    conversion_entry = Transaction(meta, last_date, flags.FLAG_CONVERSIONS,
                                   None, narration, data.EMPTY_SET,
                                   data.EMPTY_SET, [])
    for position in conversion_cost_balance.get_positions():
        # Important note: Set the cost to zero here to maintain the balance
        # invariant. (This is the only single place we cheat on the balance rule
        # in the entire system and this is necessary; see documentation on
        # Conversions.)
        price = amount.Amount(ZERO, conversion_currency)
        neg_pos = -position
        conversion_entry.postings.append(
            data.Posting(conversion_account, neg_pos.units, neg_pos.cost,
                         price, None, None))

    # Make a copy of the list of entries and insert the new transaction into it.
    new_entries = list(entries)
    new_entries.insert(index, conversion_entry)

    return new_entries
Beispiel #5
0
def truncate(entries, date):
    """Filter out all the entries at and after date. Returns a new list of entries.

    Args:
      entries: A sorted list of directives.
      date: A datetime.date instance.
    Returns:
      A truncated list of directives.
    """
    index = bisect_key.bisect_left_with_key(entries, date,
                                            key=lambda entry: entry.date)
    return entries[:index]
Beispiel #6
0
 def _entries_in_inclusive_range(self,
                                 entries,
                                 begin_date=None,
                                 end_date=None):
     """
     Returns the list of entries satisfying begin_date <= date <= end_date.
     """
     get_date = lambda x: x.date
     if begin_date is None:
         begin_index = 0
     else:
         begin_index = bisect_key.bisect_left_with_key(entries,
                                                       begin_date,
                                                       key=get_date)
     if end_date is None:
         end_index = len(entries)
     else:
         end_index = bisect_key.bisect_left_with_key(entries,
                                                     end_date +
                                                     timedelta(days=1),
                                                     key=get_date)
     return entries[begin_index:end_index]
    def test_bisect_left_with_key(self):
        second = lambda x: x[1]

        data = [(random.random(), i) for i in range(100)]
        index = bisect_key.bisect_left_with_key(data, 40, key=second)
        self.assertEqual(index, 40)
        self.assertEqual(data[index][1], 40)

        index = bisect_key.bisect_left_with_key(data, 0, key=second)
        self.assertEqual(index, 0)
        self.assertEqual(data[index][1], 0)

        index = bisect_key.bisect_left_with_key(data, -1, key=second)
        self.assertEqual(index, 0)
        self.assertEqual(data[index][1], 0)

        index = bisect_key.bisect_left_with_key(data, 99, key=second)
        self.assertEqual(index, 99)

        index = bisect_key.bisect_left_with_key(data, 100, key=second)
        self.assertEqual(index, 100)

        index = bisect_key.bisect_left_with_key(data, 999, key=second)
        self.assertEqual(index, 100)
 def test_bisect_repeats(self):
     data = [('a', 0), ('b', 0), ('c', 1), ('d', 3), ('e', 4), ('f', 4),
             ('g', 5), ('h', 6)]
     index = bisect_key.bisect_left_with_key(data, 4, key=lambda x: x[1])
     self.assertEqual(index, 4)
     self.assertEqual(data[index][0], 'e')