-
Notifications
You must be signed in to change notification settings - Fork 52
Description
The comment in importers/csvbase.py says "The CSV Importer class needs to inherit from beangulp.Importer". The implementation assumes direct inheritance, but I think we can support indirect inheritance fairly easily.
I ran into this limitation when I tried to model multiple accounts at the same bank with inheritance, which all share the same schema:
class MyBankCSVImporter(csvbase.Importer):
'''Base class for the CSV schema used by my bank'''
date = csvbase.Date("Date", "%m/%d/%Y")
# CSV schema...
class MyBankCSVImporter_Checking(MyBankCSVImporter):
'''Import data for checking account'''
def identify(self, filename: str):
return "checking_1234" in os.path.basename(filename)
class MyBankCSVImporter_Visa(MyBankCSVImporter):
'''Import data for visa card ending in 5678'''
def identify(self, filename: str):
return "visa_5678" in os.path.basename(filename)CSVReader's read(...) function uses self.columns.items() to dynamically generate a 'Row' type. For the derived classes like MyBankCSVImporter_Checking, self.columns is an empty dictionary because CSVMeta only considers data members added by the most-derived class.
My proposal would be that CSVMeta class should merge the columns added by the base class(es) in between dct and beangulp.Importer. What do you think?
class CSVMeta(abc.ABCMeta):
"""A metaclass that extracts column specifications from class members
and stores them in a columns dictionary keyed by the member name."""
def __new__(mcs, name, bases, dct):
columns = {}
others = {}
+ for b in bases:
+ if issubclass(b, beangulp.Importer) and b != beangulp.Importer:
+ columns = b.columns | columns
for key, value in dct.items():
if isinstance(value, Column):
columns[key] = value
continue
others[key] = value
others['columns'] = columns
return super().__new__(mcs, name, bases, others)