[chirp_devel] [PATCH] [csv] Add support for reading CSV generated by RT Systems software. #477
# HG changeset patch # User Tom Hayward tom@tomh.us # Date 1359657053 28800 # Node ID 1342e53677bc349c122abefed026e59a252a83e6 # Parent 6ab7af5660d5826d54b7a6487b4e0f8b0e754a60 [csv] Add support for reading CSV generated by RT Systems software. #477
diff -r 6ab7af5660d5 -r 1342e53677bc chirp/chirp_common.py --- a/chirp/chirp_common.py Tue Jan 29 14:21:28 2013 -0800 +++ b/chirp/chirp_common.py Thu Jan 31 10:30:53 2013 -0800 @@ -185,6 +185,13 @@
def parse_freq(freqstr): """Parse a frequency string and return the value in integral Hz""" + if freqstr == " ": + return 0 + elif freqstr.endswith(" MHz"): + return parse_freq(freqstr.split(" ")[0]) + elif freqstr.endswith(" kHz"): + return int(freqstr.split(" ")[0]) * 1000 + if "." in freqstr: mhz, khz = freqstr.split(".") else: diff -r 6ab7af5660d5 -r 1342e53677bc chirp/generic_csv.py --- a/chirp/generic_csv.py Tue Jan 29 14:21:28 2013 -0800 +++ b/chirp/generic_csv.py Thu Jan 31 10:30:53 2013 -0800 @@ -46,6 +46,26 @@ MODEL = "CSV" FILE_EXTENSION = "csv"
+ # To accept other software's CSV format + DUPLEX_MAP = { + "Minus": "-", + "Plus": "+", + "Simplex": "", + "Split": "split", + } + + SKIP_MAP = { + "Off": "", + "On": "S", + "P Scan": "P", + "Skip": "S", + } + + TMODE_MAP = { + "None": "", + "T Sql": "TSQL", + } + ATTR_MAP = { "Location" : (int, "number"), "Name" : (str, "name"), @@ -59,11 +79,21 @@ "DtcsPolarity" : (str, "dtcs_polarity"), "Mode" : (str, "mode"), "TStep" : (float, "tuning_step"), - "Skip" : (str, "skip"), + "Skip" : (lambda v: CSVRadio.SKIP_MAP.get(v, v), "skip"), "URCALL" : (str, "dv_urcall"), "RPT1CALL" : (str, "dv_rpt1call"), "RPT2CALL" : (str, "dv_rpt2call"), "Comment" : (str, "comment"), + + # To accept other software's CSV format + "Channel Number": (int, "number"), + "Receive Frequency":(chirp_common.parse_freq, "freq"), + "Offset Frequency": (chirp_common.parse_freq, "offset"), + "Offset Direction": (lambda v: CSVRadio.DUPLEX_MAP.get(v, v), "duplex"), + "Operating Mode": (str, "mode"), + "Tone Mode": (lambda v: CSVRadio.TMODE_MAP.get(v, v), "tmode"), + "CTCSS": (lambda v: float(v.split(" ")[0]), "rtone"), + "Step": (lambda v: float(v.split(" ")[0]), "tuning_step"), }
def _blank(self): @@ -128,6 +158,15 @@ except Exception, e: raise Exception("[%s] %s" % (attr, e))
+ if mem.duplex == "split": + header = "Transmit Frequency" + try: + val = get_datum_by_header(headers, line, header) + val = chirp_common.parse_freq(val) + mem.offset = val + except OmittedHeaderError: + pass + return mem
def load(self, filename=None):
- # To accept other software's CSV format
- DUPLEX_MAP = {
"Minus": "-",
"Plus": "+",
"Simplex": "",
"Split": "split",
- }
- SKIP_MAP = {
"Off": "",
"On": "S",
"P Scan": "P",
"Skip": "S",
}
- TMODE_MAP = {
"None": "",
"T Sql": "TSQL",
- }
- ATTR_MAP = { "Location" : (int, "number"), "Name" : (str, "name"),
@@ -59,11 +79,21 @@ "DtcsPolarity" : (str, "dtcs_polarity"), "Mode" : (str, "mode"), "TStep" : (float, "tuning_step"),
"Skip" : (str, "skip"),
"Skip" : (lambda v: CSVRadio.SKIP_MAP.get(v, v),
So, this isn't too bad as it is, but I think we might want to make it a little more explicit. This would let us more easily add additional dialects without just polluting this file with further hacks that would make it harder and harder to understand.
Right now, we traverse the list of headers specified in ATTR_MAP each time through the list. Instead, I think we should traverse those in the actual header row that we read on the first line. Then we can delegate to per-column handlers if need be, to do the actual work. This is overly complicated, but might be syntactically nice:
fname = "process_%s" % header.replace(" ", "_") if hasattr(self, fname): handled = getattr(self, fname)(mem, attr, datum, typ) if not handled: setattr(mem, attr, typ(datum)
Then, you could define methods like this in the CSV driver:
def process_Tone_Mode(self, mem, attr, datum, typ): tmode_map = { "None": "", "T Sql": "TSQL, } setattr(mem, attr, tmode_map[datum]_ return True
Another alternative might be to do what a lot of spreadsheets do, which is take a run through the first ten lines or so (or just the header, if that is enough) and try to detect the dialect. If it is know, then we delegate to a subclass of the CSV driver, with less magic and more explicit behavior. What do you think? It would probably result in less code re-use, but might be a little easier to understand.
participants (2)
-
Dan Smith
-
Tom Hayward