def getsubcategory(categoryname): try: logger.debug('searching for subcategory %s' % categoryname) return subcategories[categoryname] except KeyError: get_logger(args).debug('Couldn''t find this category: %s' % categoryname) exit(-1)
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 csvimport_main(): print('pynYNAB CSV import') """Manually import a CSV into a nYNAB budget""" parser = configargparse.getArgumentParser('pynYNAB') parser.description = inspect.getdoc(csvimport_main) parser.add_argument('csvfile', metavar='CSVpath', type=str, help='The CSV file to import') parser.add_argument('schema', metavar='schemaName', type=str, help='The CSV schema to use (see csv_schemas directory)') parser.add_argument('accountname', metavar='AccountName', type=str, nargs='?', help='The nYNAB account name to use') parser.add_argument('-import-duplicates', action='store_true', help='Forces the import even if a duplicate (same date, account, amount, memo, payee) is found') args = parser.parse_args() test_common_args(args) if not os.path.exists(args.csvfile): get_logger().error('input CSV file does not exist') exit(-1) do_csvimport(args)
def csvimport_main(): print('pynYNAB CSV import') """Manually import a CSV into a nYNAB budget""" parser = configargparse.getArgumentParser('pynYNAB') parser.description=inspect.getdoc(csvimport_main) parser.add_argument('csvfile', metavar='CSVpath', type=str, help='The CSV file to import') parser.add_argument('schema', metavar='schemaName', type=str, help='The CSV schema to use (see csv_schemas directory)') parser.add_argument('accountname', metavar='AccountName', type=str,nargs='?', help='The nYNAB account name to use') parser.add_argument('-import-duplicates', action='store_true', help='Forces the import even if a duplicate (same date, account, amount, memo, payee) is found') args = parser.parse_args() test_common_args(args) if not os.path.exists(args.csvfile): get_logger().error('input CSV file does not exist') exit(-1) do_csvimport(args)
def __init__(self, nynabconnection, budget_name): self.delta_device_knowledge = 0 self.budget_version_id = None self.logger = get_logger() if budget_name is None: logger.error('No budget name was provided') exit(-1) self.budget_name = budget_name self.connection = nynabconnection self.budget_name = budget_name self.catalog = Catalog() self.budget = Budget() self.budget_version = BudgetVersion() self.current_device_knowledge = {} self.device_knowledge_of_server = {} self.first = True self.sync()
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)
def do_csvimport(args, client=None): if client is None: client = clientfromargs(args) logger = get_logger(args) logger.debug('selected schema %s' % (args.schema,)) if os.path.exists(args.schema): schemafile = args.schema else: schemafile = os.path.join(schemas_dir, args.schema + '.json') if not os.path.exists(schemafile): logger.error('This schema doesn''t exist in csv_schemas') exit(-1) try: schema = SchemaModel(schemafile, case_insensitive_headers=True) with open(schemafile, 'r') as sf: schemacontent = json.load(sf) try: nheaders = schemacontent['nheaders'] except KeyError: nheaders = 1 except InvalidSchemaError: logger.error('Invalid CSV schema') raise logger.debug('schema headers %s' % schema.headers) if 'account' not in schema.headers and args.accountname is None: logger.error('This schema does not have an account column and no account name was provided') exit(-1) accounts = {x.account_name: x for x in client.budget.be_accounts} payees = {p.name: p for p in client.budget.be_payees} mastercategories_perid = {m.id: m for m in client.budget.be_master_categories} subcategories = {} for s in client.budget.be_subcategories: m = mastercategories_perid[s.entities_master_category_id] subcategories[m.name + ':' + s.name] = s def getaccount(accountname): try: logger.debug('searching for account %s' % accountname) return accounts[accountname] except KeyError: logger.error('Couldn''t find this account: %s' % accountname) exit(-1) def getpayee(payeename): try: logger.debug('searching for payee %s' % payeename) return payees[payeename] except KeyError: logger.debug('Couldn''t find this payee: %s' % payeename) payee = Payee(name=payeename) client.budget.be_payees.append(payee) return payee def getsubcategory(categoryname): try: logger.debug('searching for subcategory %s' % categoryname) return subcategories[categoryname] except KeyError: logger.debug('Couldn''t find this category: %s' % categoryname) exit(-1) entities_account_id = None if 'account' not in schema.headers: entities_account_id = getaccount(args.accountname).id amount = None if 'inflow' in schema.headers and 'outflow' in schema.headers: pass elif 'amount' in schema.headers: pass else: logger.error('This schema doesn''t provide an amount column or (inflow,outflow) columns') exit(-1) csvrow = namedtuple('CSVrow', field_names=schema.headers) transactions = [] imported_date = datetime.now().date() logger.debug('OK starting the import from %s ' % os.path.abspath(args.csvfile)) with open(args.csvfile, 'r') as inputfile: header = [] for i in range(0, nheaders): header.append(inputfile.readline()) for row in csv.reader(inputfile): if sys.version[0] == '2': row = [cell.decode('utf-8') for cell in row] if all(map(lambda x: x.strip() == '', row)): continue logger.debug('read line %s' % row) result = csvrow(*list(schema.convert_row(*row, fail_fast=True))) if 'account' in schema.headers: entities_account_id = getaccount(result.account).id if entities_account_id is None: logger.error( 'No account id, the account %s in the an account column was not recognized' % result.account) exit(-1) if 'inflow' in schema.headers and 'outflow' in schema.headers: amount = result.inflow - result.outflow elif 'amount' in schema.headers: amount = result.amount if 'category' in schema.headers and result.category: entities_subcategory_id = getsubcategory(result.category).id else: entities_subcategory_id = None if 'payee' in schema.headers: imported_payee = result.payee else: imported_payee = '' entities_payee_id = getpayee(imported_payee).id if 'memo' in schema.headers: memo = result.memo else: memo = '' transaction = Transaction( entities_account_id=entities_account_id, amount=amount, date=result.date, entities_payee_id=entities_payee_id, entities_subcategory_id=entities_subcategory_id, imported_date=imported_date, imported_payee=imported_payee, memo=memo, source="Imported" ) if args.import_duplicates or (not transaction in client.budget.be_transactions): logger.debug('Appending transaction %s ' % transaction.get_dict()) transactions.append(transaction) else: logger.debug('Duplicate transaction found %s ' % transaction.get_dict()) client.add_transactions(transactions)
import unittest from pynYNAB.Client import clientfromargs from pynYNAB.scripts.config import parser, get_logger # sets up the logger logger = get_logger() # used to ping the nYNAB API to check that the sync works class TestSync(unittest.TestCase): @staticmethod def test_sync(): print('test_live') args = parser.parse_known_args()[0] client = clientfromargs(args) client.sync() if __name__ == '__main__': TestSync.test_sync()
def do_csvimport(args,client=None): if client is None: client = clientfromargs(args) logger=get_logger(args) logger.debug('selected schema %s' % (args.schema,)) if os.path.exists(args.schema): schemafile = args.schema else: schemafile = os.path.join(schemas_dir, args.schema + '.json') if not os.path.exists(schemafile): logger.error('This schema doesn''t exist in csv_schemas') exit(-1) try: schema = SchemaModel(schemafile, case_insensitive_headers=True) with open(schemafile,'r') as sf: schemacontent = json.load(sf) try: nheaders = schemacontent['nheaders'] except KeyError: nheaders = 1 except InvalidSchemaError: logger.error('Invalid CSV schema') raise logger.debug('schema headers %s' % schema.headers) if 'account' not in schema.headers and args.accountname is None: logger.error('This schema does not have an account column and no account name was provided') exit(-1) accounts = {x.account_name: x for x in client.budget.be_accounts} payees = {p.name: p for p in client.budget.be_payees} mastercategories_perid = {m.id: m for m in client.budget.be_master_categories} subcategories = {} for s in client.budget.be_subcategories: m=mastercategories_perid[s.entities_master_category_id] subcategories[m.name+':'+s.name]=s def getaccount(accountname): try: logger.debug('searching for account %s' % accountname) return accounts[accountname] except KeyError: logger.error('Couldn''t find this account: %s' % accountname) exit(-1) def getpayee(payeename): try: logger.debug('searching for payee %s' % payeename) return payees[payeename] except KeyError: logger.debug('Couldn''t find this payee: %s' % payeename) payee=Payee(name=payeename) client.budget.be_payees.append(payee) return payee def getsubcategory(categoryname): try: logger.debug('searching for subcategory %s' % categoryname) return subcategories[categoryname] except KeyError: get_logger(args).debug('Couldn''t find this category: %s' % categoryname) exit(-1) if 'account' not in schema.headers: entities_account_id = getaccount(args.accountname).id if 'inflow' in schema.headers and 'outflow' in schema.headers: pass elif 'amount' in schema.headers: pass else: logger.error('This schema doesn''t provide an amount column or (inflow,outflow) columns') exit(-1) csvrow = namedtuple('CSVrow', field_names=schema.headers) transactions = [] imported_date=datetime.now().date() get_logger(args).debug('OK starting the import from %s '%os.path.abspath(args.csvfile)) with open(args.csvfile, 'r') as inputfile: header = inputfile.readline() for row in csv.reader(inputfile): if sys.version[0] == '2': row = [cell.decode('utf-8') for cell in row] if all(map(lambda x:x.strip()=='',row)): continue get_logger(args).debug('read line %s' % row) result = csvrow(*list(schema.convert_row(*row, fail_fast=True))) if 'account' in schema.headers: entities_account_id = getaccount(result.account).id if 'inflow' in schema.headers and 'outflow' in schema.headers: amount = result.inflow - result.outflow elif 'amount' in schema.headers: amount = result.amount else: get_logger(args).error('Couldn''t find this account: %s' % args.accountname) exit(-1) if 'category' in schema.headers and result.category: entities_subcategory_id = getsubcategory(result.category).id else: entities_subcategory_id = None if 'payee' in schema.headers: imported_payee=result.payee else: imported_payee='' entities_payee_id = getpayee(imported_payee).id if 'memo' in schema.headers: memo=result.memo else: memo='' transaction=Transaction( entities_account_id=entities_account_id, amount=amount, date=result.date, entities_payee_id=entities_payee_id, entities_subcategory_id=entities_subcategory_id, imported_date=imported_date, imported_payee=imported_payee, memo=memo, source="Imported" ) if args.import_duplicates or (not client.budget.be_transactions.containsduplicate(transaction)): get_logger(args).debug('Appending transaction %s '%transaction.getdict()) transactions.append(transaction) else: get_logger(args).debug('Duplicate transaction found %s '%transaction.getdict()) client.add_transactions(transactions)