def __init__(self, **kwargs): self.server_entities = {} self.budget_version_id = None self.logger = kwargs.get('logger', None) if self.logger is None: self.logger = get_logger() self.budget_name = kwargs.get('budgetname', None) if self.budget_name is None: logger.error('No budget name was provided') exit(-1) self.connection = kwargs.get('nynabconnection', None) self.catalog = Catalog() self.budget = Budget() self.budget_version = BudgetVersion() self.current_device_knowledge = {} self.device_knowledge_of_server = {} self.starting_device_knowledge = 0 self.ending_device_knowledge = 0 engine = kwargs.get('engine', create_engine('sqlite://')) Base.metadata.create_all(engine) self.Session = sessionmaker(bind=engine) self.session = self.Session() self.session.add(self.catalog) self.session.add(self.budget) self.session.commit() self.online = self.connection is not None self.catalogClient = RootObjClient(self.catalog, self, 'syncCatalogData') self.budgetClient = RootObjClient(self.budget, self, 'syncBudgetData')
def setUp(self): super(TestGetChangedEntities, self).setUp() self.obj = Budget() self.account = Account() self.obj.be_accounts = [self.account] self.obj.clear_changed_entities() self.account2 = Account(id=self.account)
class TestGetChangedEntities(CommonTest): def setUp(self): super(TestGetChangedEntities, self).setUp() self.obj = Budget() self.account = Account() self.obj.be_accounts = [self.account] self.obj.clear_changed_entities() self.account2 = Account(id=self.account) def testgetChangedEntities_add(self): added_account = Account() self.obj.be_accounts.append(added_account) changed_entities = self.obj.get_changed_entities() self.assertEqual(changed_entities, {'be_accounts': [added_account]}) def testgetChangedEntities_delete(self): self.obj.be_accounts.remove(self.account) changed_entities = self.obj.get_changed_entities() deleted = self.account.copy() deleted.is_tombstone = True self.assertEqual(changed_entities, {'be_accounts': [deleted]}) def testgetChangedEntities_modify(self): self.account.account_name = 'BLA' changed_entities = self.obj.get_changed_entities() self.assertEqual(changed_entities, {'be_accounts': [self.account]})
def setUp(self): super(TestGetChangedEntities, self).setUp() self.obj = Budget() self.account = Account() self.obj.be_accounts = [self.account] self.obj.clear_changed_entities() self.account2 = Account(id=self.account) self.client = factory.create_client(budget_name='budgetname', nynabconnection=MockConnection(), sync=False)
def test_str(self): # tests no exceptions when getting the string representation of some entities obj = Transaction() obj.__str__() obj.__unicode__() obj2 = Budget() obj2.be_accounts.__str__()
def testappendBad(self): obj = Budget() transaction = Transaction() def testappend(): obj.be_accounts.append(transaction) self.assertRaises(ValueError, testappend)
class nYnabClient(object): def __init__(self, **kwargs): self.server_entities = {} self.budget_version_id = None self.logger = kwargs.get('logger', None) if self.logger is None: self.logger = get_logger() self.budget_name = kwargs.get('budgetname', None) if self.budget_name is None: logger.error('No budget name was provided') exit(-1) self.connection = kwargs.get('nynabconnection', None) self.catalog = Catalog() self.budget = Budget() self.budget_version = BudgetVersion() self.current_device_knowledge = {} self.device_knowledge_of_server = {} self.starting_device_knowledge = 0 self.ending_device_knowledge = 0 engine = kwargs.get('engine', create_engine('sqlite://')) Base.metadata.create_all(engine) self.Session = sessionmaker(bind=engine) self.session = self.Session() self.session.add(self.catalog) self.session.add(self.budget) self.session.commit() self.online = self.connection is not None self.catalogClient = RootObjClient(self.catalog, self, 'syncCatalogData') self.budgetClient = RootObjClient(self.budget, self, 'syncBudgetData') @staticmethod def from_obj(args, reset=False, sync=True, **kwargs): try: if not hasattr(args, 'logginglevel'): setattr(args, 'logginglevel', 'error') kwargs['logger'] = get_logger(args) kwargs['budgetname'] = args.budgetname kwargs['nynabconnection'] = nYnabConnection(args.email, args.password) if hasattr(args, 'engine'): kwargs['engine'] = args.engine client = nYnabClient(**kwargs) if sync: client.sync() if reset: # deletes the budget client.delete_budget(args.budgetname) client.create_budget(args.budgetname) client.select_budget(args.budgetname) return client except BudgetNotFound: print('No budget by the name %s found in nYNAB' % args.budgetname) exit(-1) @property def extra_catalog(self): return dict(user_id=self.connection.user_id) @property def extra_budget(self): return dict(calculated_entities_included=False, budget_version_id=self.budget_version_id) def sync_catalog(self): self.catalogClient.sync(extra=self.extra_catalog) def sync_budget(self): self.budgetClient.sync(extra=self.extra_budget) def sync(self): if self.connection is None: return self.logger.debug('Client.sync') self.sync_catalog() self.select_budget(self.budget_name) self.sync_budget() if self.budget_version_id is None and self.budget_name is not None: raise BudgetNotFound() def push_budget(self): self.budgetClient.push(extra=self.extra_budget) def push_catalog(self): self.catalogClient.push(extra=self.extra_catalog) def push(self, expected_delta=1): if self.connection is None: return # ending-starting represents the number of modifications that have been done to the data ? self.logger.debug('Client.push') catalog_changed_entities = self.catalog.get_changed_apidict() budget_changed_entities = self.budget.get_changed_apidict() delta = sum(len(l) for k, l in catalog_changed_entities.items()) + \ sum(len(l) for k, l in budget_changed_entities.items()) if delta != expected_delta: raise WrongPushException(expected_delta, delta) if any(catalog_changed_entities) or any(budget_changed_entities): self.ending_device_knowledge = self.starting_device_knowledge + 1 self.push_catalog() self.push_budget() self.starting_device_knowledge = self.ending_device_knowledge self.session.commit() @operation(3) def add_account(self, account, balance, balance_date): payee = Payee( entities_account_id=account.id, enabled=True, auto_fill_subcategory_enabled=True, auto_fill_memo_enabled=False, auto_fill_amount_enabled=False, rename_on_import_enabled=False, name="Transfer : %s" % account.account_name ) immediateincomeid = next( s.id for s in self.budget.be_subcategories if s.internal_name == 'Category/__ImmediateIncome__') startingbalanceid = next(p.id for p in self.budget.be_payees if p.internal_name == 'StartingBalancePayee') transaction = Transaction( accepted=True, amount=balance, entities_subcategory_id=immediateincomeid, cash_amount=0, cleared='Cleared', date=balance_date, entities_account_id=account.id, credit_amount=0, entities_payee_id=startingbalanceid, is_tombstone=False ) self.budget.be_accounts.append(account) self.budget.be_payees.append(payee) self.budget.be_transactions.append(transaction) @operation(1) def delete_account(self, account): self.budget.be_accounts.remove(account) @operation(1) def add_transaction(self, transaction): self.budget.be_transactions.append(transaction) def add_transactions(self, transaction_list): for chunkelement in chunk(transaction_list, 50): self._add_transactions(chunkelement) @property def _add_transactions(self, transaction_list): @operation(len(transaction_list)) def _add_transactions_method(self, transaction_list): for transaction in transaction_list: self.budget.be_transactions.append(transaction) return _add_transactions_method @operation(1) def delete_transaction(self, transaction): self.budget.be_transactions.remove(transaction) @operation(1) def delete_budget(self, budget_name): for budget in self.catalog.ce_budgets: if budget.budget_name == budget_name: self.catalog.ce_budgets.remove(budget) def select_budget(self, budget_name): self.budget_version_id = None for budget_version in self.catalog.ce_budget_versions: if budget_version.version_name == budget_name: self.budget_version_id = budget_version.id if self.budget_version_id is None: raise BudgetNotFound() def create_budget(self, budget_name): import json currency_format = dict( iso_code='USD', example_format='123,456.78', decimal_digits=2, decimal_separator='.', symbol_first=True, group_separator=',', currency_symbol='$', display_symbol=True ) date_format = dict( format='MM/DD/YYYY' ) self.connection.dorequest(opname='CreateNewBudget', request_dic={ "budget_name": budget_name, "currency_format": json.dumps(currency_format), "date_format": json.dumps(date_format) })
class TestGetChangedEntities(CommonTest): def setUp(self): super(TestGetChangedEntities, self).setUp() self.obj = Budget() self.account = Account() self.obj.be_accounts = [self.account] self.obj.clear_changed_entities() self.account2 = Account(id=self.account) self.client = factory.create_client(budget_name='budgetname', nynabconnection=MockConnection(), sync=False) def testgetChangedEntities_add(self): added_account = Account() self.obj.be_accounts.append(added_account) changed_entities = self.obj.get_changed_entities() self.assertEqual(changed_entities, {'be_accounts': [added_account]}) def testgetChangedEntities_addtransactionsubtransaction(self): added_transaction = Transaction() subtransaction1 = Subtransaction( entities_transaction=added_transaction) subtransaction2 = Subtransaction( entities_transaction=added_transaction) self.client.budget.be_transactions.append(added_transaction) self.client.budget.be_subtransactions.append(subtransaction1) self.client.budget.be_subtransactions.append(subtransaction2) self.client.session.commit() changed_entities = self.client.budget.get_changed_entities() self.assertIsInstance(changed_entities, dict) self.assertEqual(1, len(changed_entities.keys())) self.assertEqual('be_transaction_groups', list(changed_entities.keys())[0]) transaction_groups = changed_entities['be_transaction_groups'] self.assertEqual(1, len(transaction_groups)) self.assertEqual(added_transaction, transaction_groups[0]['be_transaction']) self.assertIsNotNone(transaction_groups[0]['be_subtransactions']) try: self.assertItemsEqual( [subtransaction1, subtransaction2], set(transaction_groups[0]['be_subtransactions'])) except AttributeError: self.assertCountEqual( [subtransaction1, subtransaction2], set(transaction_groups[0]['be_subtransactions'])) def testgetChangedEntities_delete(self): self.obj.be_accounts.remove(self.account) changed_entities = self.obj.get_changed_entities() deleted = self.account.copy() deleted.is_tombstone = True self.assertEqual(changed_entities, {'be_accounts': [deleted]}) def testgetChangedEntities_modify(self): self.account.account_name = 'BLA' changed_entities = self.obj.get_changed_entities() self.assertEqual(changed_entities, {'be_accounts': [self.account]}) def test_arraytype(self): user = User() user.feature_flags = ['featureA', 'feature1'] self.session.add(user) self.session.commit() fetched_user = self.session.query(User).first() self.assertEqual(user, fetched_user)
def testappend(self): obj = Budget() account = Account() obj.be_accounts.append(account) self.assertEqual(len(obj.be_accounts), 1) self.assertEqual(list(obj.be_accounts)[-1], account)
def __init__(self): self.id = '1234' self.user_id = '1234' self.catalog = Catalog() self.budget = Budget()
def test_append(): obj = Budget() account = Account() obj.be_accounts.append(account) assert len(obj.be_accounts) == 1 assert list(obj.be_accounts)[-1] == account
def objclient(): client = Mock(spec=nYnabClient_) client.budget = Budget() obj_client = BudgetClient(client) return obj_client