import csv
import io
from lodstorage.jsonable import JSONAble
from lodstorage.lod import LOD
[docs]class CSV(LOD):
'''
helper for converting data in csv format to list of dicts (LoD) and vice versa
'''
[docs] @staticmethod
def restoreFromCSVFile(filePath:str, headerNames:list=None, withPostfix:bool=False):
'''
restore LOD from given csv file
Args:
filePath(str): file name
headerNames(list): Names of the headers that should be used. If None it is assumed that the header is given.
withPostfix(bool): If False the file type is appended to given filePath. Otherwise file type MUST be given with filePath.
Returns:
list of dicts (LoD) containing the content of the given csv file
'''
if not withPostfix:
filePath += ".csv"
csvStr = CSV.readFile(filePath)
lod = CSV.fromCSV(csvStr, headerNames)
return lod
[docs] @staticmethod
def fromCSV(csvString:str, fields:list=None, delimiter=",",quoting=csv.QUOTE_NONNUMERIC, **kwargs):
'''
convert given csv string to list of dicts (LOD)
Args:
csvStr(str): csv string that should be converted to LOD
headerNames(list): Names of the headers that should be used. If None it is assumed that the header is given.
Returns:
list of dicts (LoD) containing the content of the given csv string
'''
csvStream=io.StringIO(csvString)
reader = csv.DictReader(csvStream, fieldnames=fields, delimiter=delimiter, quoting=quoting, **kwargs)
lod=list(reader)
CSV.fixTypes(lod)
return lod
[docs] @staticmethod
def storeToCSVFile(lod:list, filePath:str, withPostfix:bool=False):
'''
converts the given lod to CSV file.
Args:
lod(list): lod that should be converted to csv file
filePath(str): file name the csv should be stored to
withPostfix(bool): If False the file type is appended to given filePath. Otherwise file type MUST be given with filePath.
Returns:
csv string of the given lod
'''
if not withPostfix:
filePath += ".csv"
csvStr=CSV.toCSV(lod)
CSV.writeFile(csvStr, filePath)
[docs] @staticmethod
def toCSV(lod:list, includeFields:list=None, excludeFields:list=None, delimiter=",",quoting=csv.QUOTE_NONNUMERIC, **kwargs):
'''
converts the given lod to CSV string.
For details about the csv dialect parameters see https://docs.python.org/3/library/csv.html#csv-fmt-params
Args:
lod(list): lod that should be converted to csv string
includeFields(list): list of fields that should be included in the csv (positive list)
excludeFields(list): list of fields that should be excluded from the csv (negative list)
kwargs: csv dialect parameters
Returns:
csv string of the given lod
'''
if lod is None:
return ''
if isinstance(lod[0], JSONAble):
lod=[vars(d) for d in lod]
if excludeFields is not None:
lod=LOD.filterFields(lod, excludeFields)
if includeFields is None:
fields = LOD.getFields(lod)
else:
fields=includeFields
lod=LOD.filterFields(lod, includeFields, reverse=True)
csvStream = io.StringIO()
dict_writer = csv.DictWriter(csvStream, fieldnames=fields, delimiter=delimiter, quoting=quoting, **kwargs)
dict_writer.writeheader()
dict_writer.writerows(lod)
csvString = csvStream.getvalue()
return csvString
[docs] @staticmethod
def readFile(filename: str) -> str:
"""
Reads the given filename and returns it as string
Args:
filename: Name of the file that should be returned as string
Returns:
Content of the file as string
"""
with open(filename, 'r') as file:
content = file.read()
return content
[docs] @staticmethod
def writeFile(content:str, filename: str) -> str:
"""
Write the given str to the given filename
Args:
content(str): string that should be written into the file
filename: Name of the file the given str should be written to
Returns:
Nothing
"""
with open(filename, 'w') as file:
file.write(content)
[docs] @staticmethod
def fixTypes(lod:list):
"""
fixes the types of the given LoD.
"""
for record in lod:
for key, value in record.items():
# fix empty csv value: "cell1,,cell3" converts the second value to empty string instead of None
if value == '':
record[key] = None