scripts: csv.py: Fixed incorrect fold type when type changes
csv.py's -L/--list-computed was returning some confusing types:
$ ./scripts/csv.py /dev/null -fa='float(1)' -L
a int sum
^-- huh!?
Turns out csv.py's fold typechecking was all broken. Folds can change
the type, but only at the invocation:
$ ./scripts/csv.py /dev/null -fa='sum(float(1))' -L
a int sum
$ ./scripts/csv.py /dev/null -fa='avg(int(1))' -L
a float avg
$ ./scripts/csv.py /dev/null -fa='int(avg(1))' -L
a float avg
This is maybe defensible for explicit folds, since their evaluation is
also lifted, but not so much for things like literals/fields/etc.
---
Fixed by allowing None to indicate a generic fold, and allowing types to
be lazily figured out in csv.compile.
This commit is contained in:
+10
-9
@@ -554,7 +554,7 @@ class CsvExpr:
|
|||||||
return CsvInt
|
return CsvInt
|
||||||
|
|
||||||
def fold(self, types={}):
|
def fold(self, types={}):
|
||||||
return CsvSum, CsvInt
|
return CsvSum, None
|
||||||
|
|
||||||
def eval(self, fields={}, state=None):
|
def eval(self, fields={}, state=None):
|
||||||
return self.a
|
return self.a
|
||||||
@@ -567,7 +567,7 @@ class CsvExpr:
|
|||||||
return CsvFloat
|
return CsvFloat
|
||||||
|
|
||||||
def fold(self, types={}):
|
def fold(self, types={}):
|
||||||
return CsvSum, CsvFloat
|
return CsvSum, None
|
||||||
|
|
||||||
def eval(self, fields={}, state=None):
|
def eval(self, fields={}, state=None):
|
||||||
return self.a
|
return self.a
|
||||||
@@ -585,7 +585,7 @@ class CsvExpr:
|
|||||||
def fold(self, types={}):
|
def fold(self, types={}):
|
||||||
if self.a not in types:
|
if self.a not in types:
|
||||||
raise CsvExpr.Error("unfoldable field? %s" % self.a)
|
raise CsvExpr.Error("unfoldable field? %s" % self.a)
|
||||||
return CsvSum, types[self.a]
|
return CsvSum, None
|
||||||
|
|
||||||
def eval(self, fields={}, state=None):
|
def eval(self, fields={}, state=None):
|
||||||
if self.a not in fields:
|
if self.a not in fields:
|
||||||
@@ -646,7 +646,7 @@ class CsvExpr:
|
|||||||
"""Find the sum of this column or fields"""
|
"""Find the sum of this column or fields"""
|
||||||
def fold(self, types={}):
|
def fold(self, types={}):
|
||||||
if len(self) == 1:
|
if len(self) == 1:
|
||||||
return CsvSum, self.a.type(types)
|
return CsvSum, None
|
||||||
else:
|
else:
|
||||||
return self.a.fold(types)
|
return self.a.fold(types)
|
||||||
|
|
||||||
@@ -661,7 +661,7 @@ class CsvExpr:
|
|||||||
"""Find the product of this column or fields"""
|
"""Find the product of this column or fields"""
|
||||||
def fold(self, types={}):
|
def fold(self, types={}):
|
||||||
if len(self) == 1:
|
if len(self) == 1:
|
||||||
return Prod, self.a.type(types)
|
return Prod, None
|
||||||
else:
|
else:
|
||||||
return self.a.fold(types)
|
return self.a.fold(types)
|
||||||
|
|
||||||
@@ -676,7 +676,7 @@ class CsvExpr:
|
|||||||
"""Find the minimum of this column or fields"""
|
"""Find the minimum of this column or fields"""
|
||||||
def fold(self, types={}):
|
def fold(self, types={}):
|
||||||
if len(self) == 1:
|
if len(self) == 1:
|
||||||
return CsvMin, self.a.type(types)
|
return CsvMin, None
|
||||||
else:
|
else:
|
||||||
return self.a.fold(types)
|
return self.a.fold(types)
|
||||||
|
|
||||||
@@ -691,7 +691,7 @@ class CsvExpr:
|
|||||||
"""Find the maximum of this column or fields"""
|
"""Find the maximum of this column or fields"""
|
||||||
def fold(self, types={}):
|
def fold(self, types={}):
|
||||||
if len(self) == 1:
|
if len(self) == 1:
|
||||||
return CsvMax, self.a.type(types)
|
return CsvMax, None
|
||||||
else:
|
else:
|
||||||
return self.a.fold(types)
|
return self.a.fold(types)
|
||||||
|
|
||||||
@@ -796,7 +796,7 @@ class CsvExpr:
|
|||||||
return CsvInt
|
return CsvInt
|
||||||
|
|
||||||
def fold(self, types={}):
|
def fold(self, types={}):
|
||||||
return CsvSum, CsvInt
|
return CsvSum, None
|
||||||
|
|
||||||
def eval(self, fields={}, state=None):
|
def eval(self, fields={}, state=None):
|
||||||
if state is None:
|
if state is None:
|
||||||
@@ -1622,7 +1622,8 @@ def compile(fields_, results,
|
|||||||
folds___ = {k: (CsvSum, t) for k, v in types__.items()}
|
folds___ = {k: (CsvSum, t) for k, v in types__.items()}
|
||||||
for k, expr in exprs.items():
|
for k, expr in exprs.items():
|
||||||
folds___[k] = expr.fold(types__)
|
folds___[k] = expr.fold(types__)
|
||||||
folds___ = {k: (f(), t) for k, (f, t) in folds___.items()}
|
# instantiate folds and resolve fold types
|
||||||
|
folds___ = {k: (f(), t or types___[k]) for k, (f, t) in folds___.items()}
|
||||||
|
|
||||||
# create result class
|
# create result class
|
||||||
def __new__(cls, _state=None, **r):
|
def __new__(cls, _state=None, **r):
|
||||||
|
|||||||
Reference in New Issue
Block a user