# Path: core/util.py
# def dedupe(iterable):
#     """Returns a list of elements in ``iterable`` with all dupes removed.
# 
#     The order of the elements is preserved.
#     """
#     result = []
#     seen = {}
#     for item in iterable:
#         if item in seen:
#             continue
#         seen[item] = 1
#         result.append(item)
#     return result
# 
# def nonone(value, replace_value):
#     """Returns ``value`` if ``value`` is not ``None``. Returns ``replace_value`` otherwise.
#     """
#     if value is None:
#         return replace_value
#     else:
#         return value
# 
# Path: core/const.py
# class AccountType:
#     """Enum of all possible account types.
# 
#     * ``Asset``
#     * ``Liability``
#     * ``Income``
#     * ``Expense``
# 
#     Special values:
# 
#     * ``All``: set containing all account types
#     * ``InOrder``: all account type in "sort" order.
#     """
#     Asset = 'asset'
#     Liability = 'liability'
#     Income = 'income'
#     Expense = 'expense'
#     InOrder = [Asset, Liability, Income, Expense]
#     All = set(InOrder)
# 
# Path: core/model/oven.py
# class Oven:
#     """Computes raw data from transactions, schedules.
# 
#     Two main things the oven :ref:`cooks <cooking>`:
# 
#     1. Spawns schedule transactions and insert them into its cooked result,
#        :attr:`transactions`. This :class:`.TransactionList` is what is then used by the rest of the
#        app to display transactions and account entries.
#     2. Creates :class:`.Entry` instances to place in :attr:`.Account.entries`. These entries contain
#        running totals for each account (which is, of course, calculated).
#     """
#     def __init__(self, accounts, transactions, scheduled):
#         self._accounts = accounts
#         self._transactions = transactions
#         self._scheduled = scheduled
#         self._cooked_until = date.min
#         #: List of cooked transactions, containing :class:`.Transaction` instances mixed with
#         #: schedule :class:`.Spawn` instances (in date/position order).
#         self.transactions = []
# 
#     def continue_cooking(self, until_date):
#         """Cooks from where we stop last time until ``until_date``.
# 
#         Cooking dates are often determined by the current date range, so when we advance or enlarge
#         our date range, we usually need to cook a bit further than where we stopped last time.
# 
#         This is what this method is about.
#         """
#         if until_date > self._cooked_until:
#             self.cook(self._cooked_until, until_date)
# 
#     def cook(self, from_date=None, until_date=None):
#         """Cooks raw data into :attr:`transactions`.
# 
#         :param from_date: when set, saves calculation time by re-using existing cooked transactions.
#         :type from_date: ``datetime.date``
#         :param until_date: because of recurrence, we must always have a date at which we stop
#                            cooking. If we don't, we might end up in an infinite loop. If not set,
#                            will be the date of the transaction with the highest date.
#         :type until_date: ``datetime.date``
#         """
#         # Determine from/until dates
#         if from_date is None:
#             from_date = date.min
#         else:
#             # it's possible that we have to reduce from_date a bit. If a split
#             # from before as a reconciled date >= from_date, we have to set
#             # from_date to that split's normal date We reverse the transactions
#             # to correctly detect chained overlappings in date/recdate
#             # Moreover, to avoid bad memory access, we don't want `from_date`
#             # to be later than the earliest schedule spawn we have.
#             for txn in reversed(self.transactions): # splits from *cooked* txns
#                 if txn.is_spawn:
#                     from_date = min(from_date, txn.date)
#                     continue
#                 for split in txn.splits:
#                     rdate = split.reconciliation_date
#                     if rdate is not None and rdate >= from_date:
#                         from_date = min(from_date, txn.date)
#         self._transactions.sort() # needed in case until_date is None
#         if until_date is None:
#             until_date = self._transactions.last().date if self._transactions else from_date
#         # Clear old cooked data
#         if from_date == date.min:
#             self.transactions = []
#         else:
#             self.transactions = [t for t in self.transactions if t.date < from_date]
#         # Cook
#         cooked = oven_cook_txns(
#             self._accounts, self._transactions, self._scheduled or [],
#             from_date, until_date)
#         self.transactions += cooked
#         self._cooked_until = until_date


import datetime
import re
from core.util import dedupe, nonone
from core.trans import tr
from ..const import AccountType
from ..exception import FileFormatError
from ..model._ccore import (
    AccountList, TransactionList, UnsupportedCurrencyError, amount_parse, Transaction)
from ..model.currency import Currencies
from ..model.oven import Oven
EXTRA_DATE_SEPS = ['.', '-', ' ']
DATE_FORMATS = BASE_DATE_FORMATS[:]
# Re-add all date formats with their separator replaced
for sep in EXTRA_DATE_SEPS:
    for base_format in BASE_DATE_FORMATS:
        DATE_FORMATS.append(base_format.replace('/', sep))
# Finally, add special formats
DATE_FORMATS += ['%m/%d\'%y', '%Y%m%d']

POSSIBLE_PATTERNS = [
    r'[\d/.\- ]{6,10}',
    r'\d{1,2}[/.\- ]\w{3}[/.\- ]\d{2,4}',
    r"\d{1,2}/\d{1,2}'\d{2,4}",
]
re_possibly_a_date = re.compile('|'.join(POSSIBLE_PATTERNS))

def parse_amount(string, currency, **kwargs):
    try:
        return amount_parse(
            string, currency, with_expression=False, **kwargs)
    except UnsupportedCurrencyError:
        msg = tr(
            "Unsupported currency: {}. Aborting load. Did you disable a currency plugin?"
        ).format(currency)
        raise FileFormatError(msg)

def get_account_type(type):
    if type in AccountType.All:
        return type
    else:

# Path: core/util.py
# def dedupe(iterable):
#     """Returns a list of elements in ``iterable`` with all dupes removed.
# 
#     The order of the elements is preserved.
#     """
#     result = []
#     seen = {}
#     for item in iterable:
#         if item in seen:
#             continue
#         seen[item] = 1
#         result.append(item)
#     return result
# 
# def nonone(value, replace_value):
#     """Returns ``value`` if ``value`` is not ``None``. Returns ``replace_value`` otherwise.
#     """
#     if value is None:
#         return replace_value
#     else:
#         return value
# 
# Path: core/const.py
# class AccountType:
#     """Enum of all possible account types.
# 
#     * ``Asset``
#     * ``Liability``
#     * ``Income``
#     * ``Expense``
# 
#     Special values:
# 
#     * ``All``: set containing all account types
#     * ``InOrder``: all account type in "sort" order.
#     """
#     Asset = 'asset'
#     Liability = 'liability'
#     Income = 'income'
#     Expense = 'expense'
#     InOrder = [Asset, Liability, Income, Expense]
#     All = set(InOrder)
# 
# Path: core/model/oven.py
# class Oven:
#     """Computes raw data from transactions, schedules.
# 
#     Two main things the oven :ref:`cooks <cooking>`:
# 
#     1. Spawns schedule transactions and insert them into its cooked result,
#        :attr:`transactions`. This :class:`.TransactionList` is what is then used by the rest of the
#        app to display transactions and account entries.
#     2. Creates :class:`.Entry` instances to place in :attr:`.Account.entries`. These entries contain
#        running totals for each account (which is, of course, calculated).
#     """
#     def __init__(self, accounts, transactions, scheduled):
#         self._accounts = accounts
#         self._transactions = transactions
#         self._scheduled = scheduled
#         self._cooked_until = date.min
#         #: List of cooked transactions, containing :class:`.Transaction` instances mixed with
#         #: schedule :class:`.Spawn` instances (in date/position order).
#         self.transactions = []
# 
#     def continue_cooking(self, until_date):
#         """Cooks from where we stop last time until ``until_date``.
# 
#         Cooking dates are often determined by the current date range, so when we advance or enlarge
#         our date range, we usually need to cook a bit further than where we stopped last time.
# 
#         This is what this method is about.
#         """
#         if until_date > self._cooked_until:
#             self.cook(self._cooked_until, until_date)
# 
#     def cook(self, from_date=None, until_date=None):
#         """Cooks raw data into :attr:`transactions`.
# 
#         :param from_date: when set, saves calculation time by re-using existing cooked transactions.
#         :type from_date: ``datetime.date``
#         :param until_date: because of recurrence, we must always have a date at which we stop
#                            cooking. If we don't, we might end up in an infinite loop. If not set,
#                            will be the date of the transaction with the highest date.
#         :type until_date: ``datetime.date``
#         """
#         # Determine from/until dates
#         if from_date is None:
#             from_date = date.min
#         else:
#             # it's possible that we have to reduce from_date a bit. If a split
#             # from before as a reconciled date >= from_date, we have to set
#             # from_date to that split's normal date We reverse the transactions
#             # to correctly detect chained overlappings in date/recdate
#             # Moreover, to avoid bad memory access, we don't want `from_date`
#             # to be later than the earliest schedule spawn we have.
#             for txn in reversed(self.transactions): # splits from *cooked* txns
#                 if txn.is_spawn:
#                     from_date = min(from_date, txn.date)
#                     continue
#                 for split in txn.splits:
#                     rdate = split.reconciliation_date
#                     if rdate is not None and rdate >= from_date:
#                         from_date = min(from_date, txn.date)
#         self._transactions.sort() # needed in case until_date is None
#         if until_date is None:
#             until_date = self._transactions.last().date if self._transactions else from_date
#         # Clear old cooked data
#         if from_date == date.min:
#             self.transactions = []
#         else:
#             self.transactions = [t for t in self.transactions if t.date < from_date]
#         # Cook
#         cooked = oven_cook_txns(
#             self._accounts, self._transactions, self._scheduled or [],
#             from_date, until_date)
#         self.transactions += cooked
#         self._cooked_until = until_date


# Path: core/loader/base.py
import datetime
import re
from core.util import dedupe, nonone
from core.trans import tr
from ..const import AccountType
from ..exception import FileFormatError
from ..model._ccore import (
    AccountList, TransactionList, UnsupportedCurrencyError, amount_parse, Transaction)
from ..model.currency import Currencies
from ..model.oven import Oven

EXTRA_DATE_SEPS = ['.', '-', ' ']
DATE_FORMATS = BASE_DATE_FORMATS[:]
# Re-add all date formats with their separator replaced
for sep in EXTRA_DATE_SEPS:
    for base_format in BASE_DATE_FORMATS:
        DATE_FORMATS.append(base_format.replace('/', sep))
# Finally, add special formats
DATE_FORMATS += ['%m/%d\'%y', '%Y%m%d']

POSSIBLE_PATTERNS = [
    r'[\d/.\- ]{6,10}',
    r'\d{1,2}[/.\- ]\w{3}[/.\- ]\d{2,4}',
    r"\d{1,2}/\d{1,2}'\d{2,4}",
]
re_possibly_a_date = re.compile('|'.join(POSSIBLE_PATTERNS))

def parse_amount(string, currency, **kwargs):
    try:
        return amount_parse(
            string, currency, with_expression=False, **kwargs)
    except UnsupportedCurrencyError:
        msg = tr(
            "Unsupported currency: {}. Aborting load. Did you disable a currency plugin?"
        ).format(currency)
        raise FileFormatError(msg)

def get_account_type(type):
    if type in AccountType.All:
        return type
    else:

        return AccountType.Asset