示例#1
0
 def test_validate_documents_paths(self):
     date = datetime.date(2014, 3, 3)
     meta = data.new_metadata('<validation_test>', 0)
     entries = [
         data.Document(meta, date, 'Assets:Account1',
                       "/abs/path/to/something.pdf"),
         data.Document(meta, date, 'Assets:Account2',
                       "relative/something.pdf"),
         data.Document(meta, date, 'Assets:Account2', "../something.pdf"),
         data.Document(meta, date, 'Assets:Account2', "")
     ]
     errors = validation.validate_documents_paths(entries, {})
     self.assertEqual(3, len(errors))
     self.assertEqual({'Assets:Account2'},
                      set(error.entry.account for error in errors))
示例#2
0
def unwrap_entry(data: dict) -> bean.Directive:
    type, e = itemgetter("type", "entry")(data)
    meta = e.get("meta")
    date = parse_date(e["date"])
    if type == "Open":
        return bean.Open(
            meta,
            date,
            account=e["account"],
            currencies=e.get("currencies", []),
            booking=e.get("booking"),
        )
    if type == "Close":
        return bean.Close(meta, date, account=e["account"])
    if type == "Commodity":
        return bean.Commodity(meta, date, currency=e["currency"])
    if type == "Pad":
        return bean.Pad(meta,
                        date,
                        account=e["account"],
                        source_account=e["source_account"])
    if type == "Balance":
        return bean.Balance(
            meta,
            date,
            account=e["account"],
            amount=parse_amount(e["amount"]),
            tolerance=e.get("tolerance"),
            diff_amount=e.get("diff_amount"),
        )
    if type == "Transaction":
        return bean.Transaction(
            meta,
            date,
            flag=e["flag"],
            payee=e.get("payee"),
            narration=e["narration"],
            tags=set(e["tags"] if "tags" in e else []),
            links=set(e["links"] if "links" in e else []),
            postings=[parse_posting(p) for p in e.get("postings", [])],
        )
    if type == "Note":
        return bean.Note(meta,
                         date,
                         account=e["account"],
                         comment=e.get("comment", ""))
    if type == "Event":
        return bean.Event(meta,
                          date,
                          type=e["type"],
                          description=e["description"])
    if type == "Query":
        return bean.Query(meta,
                          date,
                          name=e["name"],
                          query_string=e["query_string"])
    if type == "Price":
        return bean.Price(meta,
                          date,
                          currency=e["currency"],
                          amount=parse_amount(e["amount"]))
    if type == "Document":
        return bean.Document(
            meta,
            date,
            account=e["account"],
            filename=e["filename"],
            tags=set(e["tags"] if "tags" in e else []),
            links=set(e["links"] if "links" in e else []),
        )
    if type == "Custom":
        return bean.Custom(meta, date, type=e["type"], values=e["values"])
示例#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 is not None 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)
            try:
                date = datetime.date(*map(int, match.group(1, 2, 3)))
            except ValueError as exc:
                errors.append(
                    DocumentError(
                        data.new_metadata(input_filename, 0),
                        "Invalid date on document file '{}': {}".format(
                            filename, exc), None))
            else:
                entry = data.Document(meta, date, account_name,
                                      path.join(root, filename),
                                      data.EMPTY_SET, data.EMPTY_SET)
                entries.append(entry)

    return (entries, errors)