def common_root(accounts): r''' >>> a = Account(label='a') >>> b = Account(label='b', parent=a, tags=['x']) >>> c = Account(label='c', parent=b, tags=['y']) >>> d = Account(label='d', parent=a, atype=AccountType.ProfitLoss) >>> e = Account(label='e', tags=['a', 'b']) >>> f = Account(label='f', parent=b) >>> common_root([c]).label 'c' >>> common_root([c, d]).label 'a' >>> common_root([b, c]).label 'b' >>> common_root([c, e]) is None True >>> common_root([c, f]).label 'b' ''' roots = None for account in accounts: if roots is None: roots = set(account.self_and_all_parents()) else: roots.intersection_update(account.self_and_all_parents()) if not roots: return None while len(roots) > 1: for account in list(roots): roots.difference_update(account.all_parents()) assert len(roots) == 1 return roots.pop()
def tree(self, title, accounts, amount_columns, depth=None): if depth is not None: accounts = set(a for a in accounts if a.depth() <= depth) accounts = filter_display_accounts(accounts, self.opts) # TODO refactor filter_display_accounts() as method of Formatter subaccounts = parentset(accounts) all_accounts = [None] + list(sorted(accounts | subaccounts)) while all_accounts: account = all_accounts.pop(0) is_subaccount = account in subaccounts if not self.opt_subtotals and self.opt_fullnames and is_subaccount: continue if account is None: if self.opt_bare: continue text = 'TOTAL ' + title elif self.opt_fullnames: text = str(account) else: def has_sibling(account): if not all_accounts: return False for a in all_accounts: if a.depth() <= account.depth(): break return a.depth() == account.depth() graph = ['├─╴' if has_sibling(account) else '└─╴'] for a in account.all_parents(): graph.append('│ ' if has_sibling(a) else ' ') if self.opt_bare: graph.pop() text = ''.join(reversed(graph)) + account.bare_name() columns = [] for acol in amount_columns: if (account is None or self.opt_subtotals or not is_subaccount) and account in acol: columns.append(self.config.format_money(acol[account])) else: columns.append('') yield self.fmt(text + ' ', ((' ' + c if c else '') for c in columns), label= (account and account.label) or '', text_fill= '' if is_subaccount else '.', column_fill= '' if is_subaccount else '.', strong= self.opt_subtotals and not is_subaccount)