示例#1
0
    def test_walk(self):
        actual_data = [
            (root[len(self.root):], account_, dirs, files)
            for root, account_, dirs, files in account.walk(self.root)]

        self.assertEqual([
            ('/Assets/US', 'Assets:US',
             ['Bank'],
             []),
            ('/Assets/US/Bank', 'Assets:US:Bank',
             ['Checking', 'Savings'],
             []),
            ('/Assets/US/Bank/Checking', 'Assets:US:Bank:Checking',
             ['otherdir'],
             ['2014-06-08.bank-statement.pdf', 'other.txt']),

            ('/Assets/US/Bank/Savings', 'Assets:US:Bank:Savings',
             [],
             ['2014-07-01.savings.pdf']),

            ('/Liabilities/US', 'Liabilities:US',
             ['Bank'],
             []),
            ('/Liabilities/US/Bank', 'Liabilities:US:Bank',
             [],
             []),
            ], actual_data)
示例#2
0
def validate_directory(accounts, document_dir):
    """Check a directory hierarchy against a list of valid accounts.

    Walk the directory hierarchy, and for all directories with names matching
    that of accounts (with ":" replaced with "/"), check that they refer to an
    account name declared in the given list.

    Args:
      account: A set or dict of account names.
      document_dir: A string, the root directory to walk and validate.
    Returns:
      An errors for each invalid directory name found.
    """
    # Generate all parent accounts in the account_set we're checking against, so
    # that parent directories with no corresponding account don't warn.
    accounts_with_parents = set(accounts)
    for account_ in accounts:
        while True:
            parent = account.parent(account_)
            if not parent:
                break
            if parent in accounts_with_parents:
                break
            accounts_with_parents.add(parent)
            account_ = parent

    errors = []
    for directory, account_name, _, _ in account.walk(document_dir):
        if account_name not in accounts_with_parents:
            errors.append(
                ValidateDirectoryError(
                    "Invalid directory '{}': no corresponding account '{}'".
                    format(directory, account_name)))
    return errors
示例#3
0
def find_documents(directory,
                   input_filename,
                   accounts_only=None,
                   strict=False):
    """Find dated document files under the given directory.

    If a restricting set of accounts is provided in 'accounts_only', only return
    entries that correspond to one of the given accounts.

    Args:
      directory: A string, the name of the root of the directory hierarchy to be searched.
      input_filename: The name of the file to be used for the Document directives. This is
        also used to resolve relative directory names.
      accounts_only: A set of valid accounts strings to search for.
      strict: A boolean, set to true if you want to generate errors on documents
        found in accounts not provided in accounts_only. This is only meaningful
        if accounts_only is specified.
    Returns:
      A list of new Document objects that were created from the files found, and a list
      of new errors generated.

    """
    errors = []

    # Compute the documents directory name relative to the beancount input
    # file itself.
    if not path.isabs(directory):
        input_directory = path.dirname(input_filename)
        directory = path.abspath(
            path.normpath(path.join(input_directory, directory)))

    # If the directory does not exist, just generate an error and return.
    if not path.exists(directory):
        meta = data.new_metadata(input_filename, 0)
        error = DocumentError(
            meta, "Document root '{}' does not exist".format(directory), None)
        return ([], [error])

    # Walk the hierarchy of files.
    entries = []
    for root, account_name, dirs, files in account.walk(directory):

        # Look for files that have a dated filename.
        for filename in files:
            match = re.match('(\d\d\d\d)-(\d\d)-(\d\d).(.*)', filename)
            if not match:
                continue

            # If a restricting set of accounts was specified, skip document
            # directives found in accounts with no corresponding account name.
            if accounts_only and not account_name in accounts_only:
                if strict:
                    if any(
                            account_name.startswith(account)
                            for account in accounts_only):
                        errors.append(
                            DocumentError(
                                data.new_metadata(input_filename, 0),
                                "Document '{}' found in child account {}".
                                format(filename, account_name), None))
                    elif any(
                            account.startswith(account_name)
                            for account in accounts_only):
                        errors.append(
                            DocumentError(
                                data.new_metadata(input_filename, 0),
                                "Document '{}' found in parent account {}".
                                format(filename, account_name), None))
                continue

            # Create a new directive.
            meta = data.new_metadata(input_filename, 0)
            date = datetime.date(*map(int, match.group(1, 2, 3)))
            entry = Document(meta, date, account_name,
                             path.join(root, filename))
            entries.append(entry)

    return (entries, errors)