# Path: budgettracker/data.py
# def split_income_expenses(transactions):
#     income = filter(lambda tx: tx.amount > 0.0, transactions)
#     expenses = filter(lambda tx: tx.amount <= 0.0, transactions)
#     return income, expenses
# 
# def extract_transactions_by_label(transactions, labels):
#     def match_label(tx):
#         for exp in labels:
#             if re.match(exp, tx.label):
#                 return True
#         return False
#     matching = filter(match_label, transactions)
#     transactions = filter_out_transactions(transactions, matching)
#     return matching, transactions
# 
# def filter_transactions_period(transactions, start_date=None, end_date=None):
#     if not start_date and not end_date:
#         return transactions
#     return filter(
#         lambda tx: (not start_date or tx.date >= start_date) and (not end_date or tx.date < end_date),
#         transactions)
# 
# def sort_transactions(transactions):
#     return sorted(transactions, key=lambda tx: tx.date, reverse=True)
# 
# def period_to_months(start_date, end_date):
#     dates = [start_date.replace(day=1)]
#     end_date = end_date.replace(day=1) - monthdelta(1)
#     while dates[-1] < end_date:
#         dates.append(dates[-1] + monthdelta(1))
#     return dates


from collections import namedtuple, OrderedDict
from .data import (split_income_expenses, extract_transactions_by_label, filter_transactions_period,
                   sort_transactions, period_to_months)
from monthdelta import monthdelta
import datetime
    budgets = BudgetList()
    for date in period_to_months(start_date, end_date):
        budgets.append(budgetize_month(transactions, date, *args, **kwargs))
    return budgets


def budgetize_month(transactions, date, income_sources=None, planned_expenses=None, budget_goals=None, income_delay=0):
    start_date = date.replace(day=1)
    end_date = start_date + monthdelta(1)

    if income_delay:
        income_transactions, _ = split_income_expenses(filter_transactions_period(
        transactions, start_date + datetime.timedelta(days=income_delay), end_date + datetime.timedelta(days=income_delay)))
        _, expenses_transactions = split_income_expenses(filter_transactions_period(transactions, start_date, end_date))
        transactions = sort_transactions(income_transactions + expenses_transactions)
    else:
        transactions = sort_transactions(filter_transactions_period(transactions, start_date, end_date))
        income_transactions, expenses_transactions = split_income_expenses(transactions)

    expected_income = 0
    if income_sources:
        income_sources = filter_period(income_sources, start_date, end_date)
        expected_income = sum([src.amount for src in income_sources])

    planned_expenses_transactions = []
    expected_planned_expenses = 0
    if planned_expenses:
        planned_expenses = filter_period(planned_expenses, start_date, end_date)
        planned_expenses_labels = [exp.match for exp in planned_expenses if exp.match]
        expected_planned_expenses = sum([exp.amount_per_month for exp in planned_expenses])

# Path: budgettracker/data.py
# def split_income_expenses(transactions):
#     income = filter(lambda tx: tx.amount > 0.0, transactions)
#     expenses = filter(lambda tx: tx.amount <= 0.0, transactions)
#     return income, expenses
# 
# def extract_transactions_by_label(transactions, labels):
#     def match_label(tx):
#         for exp in labels:
#             if re.match(exp, tx.label):
#                 return True
#         return False
#     matching = filter(match_label, transactions)
#     transactions = filter_out_transactions(transactions, matching)
#     return matching, transactions
# 
# def filter_transactions_period(transactions, start_date=None, end_date=None):
#     if not start_date and not end_date:
#         return transactions
#     return filter(
#         lambda tx: (not start_date or tx.date >= start_date) and (not end_date or tx.date < end_date),
#         transactions)
# 
# def sort_transactions(transactions):
#     return sorted(transactions, key=lambda tx: tx.date, reverse=True)
# 
# def period_to_months(start_date, end_date):
#     dates = [start_date.replace(day=1)]
#     end_date = end_date.replace(day=1) - monthdelta(1)
#     while dates[-1] < end_date:
#         dates.append(dates[-1] + monthdelta(1))
#     return dates


# Path: budgettracker/budget.py
from collections import namedtuple, OrderedDict
from .data import (split_income_expenses, extract_transactions_by_label, filter_transactions_period,
                   sort_transactions, period_to_months)
from monthdelta import monthdelta
import datetime

    budgets = BudgetList()
    for date in period_to_months(start_date, end_date):
        budgets.append(budgetize_month(transactions, date, *args, **kwargs))
    return budgets


def budgetize_month(transactions, date, income_sources=None, planned_expenses=None, budget_goals=None, income_delay=0):
    start_date = date.replace(day=1)
    end_date = start_date + monthdelta(1)

    if income_delay:
        income_transactions, _ = split_income_expenses(filter_transactions_period(
        transactions, start_date + datetime.timedelta(days=income_delay), end_date + datetime.timedelta(days=income_delay)))
        _, expenses_transactions = split_income_expenses(filter_transactions_period(transactions, start_date, end_date))
        transactions = sort_transactions(income_transactions + expenses_transactions)
    else:
        transactions = sort_transactions(filter_transactions_period(transactions, start_date, end_date))
        income_transactions, expenses_transactions = split_income_expenses(transactions)

    expected_income = 0
    if income_sources:
        income_sources = filter_period(income_sources, start_date, end_date)
        expected_income = sum([src.amount for src in income_sources])

    planned_expenses_transactions = []
    expected_planned_expenses = 0
    if planned_expenses:
        planned_expenses = filter_period(planned_expenses, start_date, end_date)
        planned_expenses_labels = [exp.match for exp in planned_expenses if exp.match]
        expected_planned_expenses = sum([exp.amount_per_month for exp in planned_expenses])

        planned_expenses_transactions, expenses_transactions = extract_transactions_by_label(