scripts: Added CsvFfrac type
A simple float variant of the CsvFrac type: - frac(1.5,2) => 1/2 (50.0%) - ffrac(1.5,2) => 1.5/2.0 (75.0%) Useful for `make bench-widths` (previously make bench-bus), where we want to find the average buffer utilization: probe readed progged erased b_rbyd+create 1.0/1.0 (100.0%) 13.8/256.0 (5.4%) ∞/4096.0 (∞%) b_rbyd+delete ∞/1.0 (∞%) ∞/256.0 (∞%) ∞/4096.0 (∞%) b_rbyd+fetch 1.0/1.0 (100.0%) ∞/256.0 (∞%) ∞/4096.0 (∞%) b_rbyd+lookup 1.0/1.0 (100.0%) ∞/256.0 (∞%) ∞/4096.0 (∞%) b_rbyd+usage ∞/1.0 (∞%) ∞/256.0 (∞%) ∞/4096.0 (∞%) b_wt_seq+w 1.0/1.0 (100.0%) 31.7/256.0 (12.4%) 4096.0/4096.0 (100.0%) b_wt_random+w 1.0/1.0 (100.0%) 15.3/256.0 (6.0%) 4096.0/4096.0 (100.0%) b_wt_logging+w 1.0/1.0 (100.0%) 15.4/256.0 (6.0%) 4096.0/4096.0 (100.0%) b_wt_many+w 1.0/1.0 (100.0%) 16.1/256.0 (6.3%) 4096.0/4096.0 (100.0%) TOTAL ∞/1.0 (∞%) ∞/256.0 (∞%) ∞/4096.0 (∞%) Now that we have 4 types, the cast matrix gets a bit complicated, but this is side-stepped a bit by a custom __frac__ hook. --- Some other tweaks to csv.py: - Added CsvFold.type to typecheck folds _after_ we know the expr's final type. - Adopted CsvFfrac as an output for most of the math functions/folds - Stopped early termination of typechecking if we change type! This was broken: int(float(1.5) + int(1))
This commit is contained in:
@@ -661,15 +661,30 @@ bench-ops: $(BENCH_CSV)
|
|||||||
$(SUMMARYFLAGS))
|
$(SUMMARYFLAGS))
|
||||||
|
|
||||||
## Show average readed/progged/erased per width
|
## Show average readed/progged/erased per width
|
||||||
.PHONY: bench-bus
|
.PHONY: bench-widths
|
||||||
bench-bus: SUMMARYFLAGS+=-Si
|
bench-widths: SUMMARYFLAGS+=-Si
|
||||||
bench-bus: $(BENCH_CSV)
|
bench-widths: $(BENCH_CSV)
|
||||||
$(strip ./scripts/csv.py $^ \
|
$(strip ./scripts/csv.py $^ \
|
||||||
-bprobe='%(case)s+%(probe)s' \
|
-bprobe='%(case)s+%(probe)s' \
|
||||||
-Fi='min(enumerate())' \
|
-Fi='min(enumerate())' \
|
||||||
-freaded='avg(float(bench_readed)/float(bench_reads))' \
|
-freaded="avg(ffrac( \
|
||||||
-fprogged='avg(float(bench_progged)/float(bench_progs))' \
|
float(bench_readed)/float(bench_reads), \
|
||||||
-ferased='avg(float(bench_erased)/float(bench_erases))' \
|
max(1, $$( \
|
||||||
|
./scripts/bench.py -R$(BENCH_RUNNER) $(BENCHFLAGS) \
|
||||||
|
--list-implicit-defines \
|
||||||
|
| sed -n 's/^READ_WIDTH=\(.*\)/\1/p'))))" \
|
||||||
|
-fprogged="avg(ffrac( \
|
||||||
|
float(bench_progged)/float(bench_progs), \
|
||||||
|
max(1, $$( \
|
||||||
|
./scripts/bench.py -R$(BENCH_RUNNER) $(BENCHFLAGS) \
|
||||||
|
--list-implicit-defines \
|
||||||
|
| sed -n 's/^PROG_WIDTH=\(.*\)/\1/p'))))" \
|
||||||
|
-ferased="avg(ffrac( \
|
||||||
|
float(bench_erased)/float(bench_erases), \
|
||||||
|
max(1, $$( \
|
||||||
|
./scripts/bench.py -R$(BENCH_RUNNER) $(BENCHFLAGS) \
|
||||||
|
--list-implicit-defines \
|
||||||
|
| sed -n 's/^ERASE_WIDTH=\(.*\)/\1/p'))))" \
|
||||||
$(SUMMARYFLAGS))
|
$(SUMMARYFLAGS))
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -40,7 +40,7 @@ class CsvInt(co.namedtuple('CsvInt', 'a')):
|
|||||||
def __new__(cls, a=0):
|
def __new__(cls, a=0):
|
||||||
if isinstance(a, CsvInt):
|
if isinstance(a, CsvInt):
|
||||||
return a
|
return a
|
||||||
if isinstance(a, str):
|
elif isinstance(a, str):
|
||||||
try:
|
try:
|
||||||
a = int(a, 0)
|
a = int(a, 0)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
|||||||
+8
-3
@@ -42,7 +42,7 @@ class CsvInt(co.namedtuple('CsvInt', 'a')):
|
|||||||
def __new__(cls, a=0):
|
def __new__(cls, a=0):
|
||||||
if isinstance(a, CsvInt):
|
if isinstance(a, CsvInt):
|
||||||
return a
|
return a
|
||||||
if isinstance(a, str):
|
elif isinstance(a, str):
|
||||||
try:
|
try:
|
||||||
a = int(a, 0)
|
a = int(a, 0)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
@@ -150,9 +150,11 @@ class CsvFrac(co.namedtuple('CsvFrac', 'a,b')):
|
|||||||
def __new__(cls, a=0, b=None):
|
def __new__(cls, a=0, b=None):
|
||||||
if isinstance(a, CsvFrac) and b is None:
|
if isinstance(a, CsvFrac) and b is None:
|
||||||
return a
|
return a
|
||||||
if isinstance(a, str) and b is None:
|
elif hasattr(a, '__frac__') and b is None:
|
||||||
|
a, b = a.__frac__()
|
||||||
|
elif isinstance(a, str) and b is None:
|
||||||
a, b = a.split('/', 1)
|
a, b = a.split('/', 1)
|
||||||
if b is None:
|
elif b is None:
|
||||||
b = a
|
b = a
|
||||||
return super().__new__(cls, CsvInt(a), CsvInt(b))
|
return super().__new__(cls, CsvInt(a), CsvInt(b))
|
||||||
|
|
||||||
@@ -174,6 +176,9 @@ class CsvFrac(co.namedtuple('CsvFrac', 'a,b')):
|
|||||||
def __float__(self):
|
def __float__(self):
|
||||||
return float(self.a)
|
return float(self.a)
|
||||||
|
|
||||||
|
def __frac__(self):
|
||||||
|
return self.a, self.b
|
||||||
|
|
||||||
none = '%11s' % '-'
|
none = '%11s' % '-'
|
||||||
def table(self):
|
def table(self):
|
||||||
return '%11s' % (self,)
|
return '%11s' % (self,)
|
||||||
|
|||||||
+329
-60
@@ -65,7 +65,7 @@ class CsvInt(co.namedtuple('CsvInt', 'a')):
|
|||||||
def __new__(cls, a=0):
|
def __new__(cls, a=0):
|
||||||
if isinstance(a, CsvInt):
|
if isinstance(a, CsvInt):
|
||||||
return a
|
return a
|
||||||
if isinstance(a, str):
|
elif isinstance(a, str):
|
||||||
try:
|
try:
|
||||||
a = int(a, 0)
|
a = int(a, 0)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
@@ -173,7 +173,7 @@ class CsvFloat(co.namedtuple('CsvFloat', 'a')):
|
|||||||
def __new__(cls, a=0.0):
|
def __new__(cls, a=0.0):
|
||||||
if isinstance(a, CsvFloat):
|
if isinstance(a, CsvFloat):
|
||||||
return a
|
return a
|
||||||
if isinstance(a, str):
|
elif isinstance(a, str):
|
||||||
try:
|
try:
|
||||||
a = float(a)
|
a = float(a)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
@@ -280,9 +280,11 @@ class CsvFrac(co.namedtuple('CsvFrac', 'a,b')):
|
|||||||
def __new__(cls, a=0, b=None):
|
def __new__(cls, a=0, b=None):
|
||||||
if isinstance(a, CsvFrac) and b is None:
|
if isinstance(a, CsvFrac) and b is None:
|
||||||
return a
|
return a
|
||||||
if isinstance(a, str) and b is None:
|
elif hasattr(a, '__frac__') and b is None:
|
||||||
|
a, b = a.__frac__()
|
||||||
|
elif isinstance(a, str) and b is None:
|
||||||
a, b = a.split('/', 1)
|
a, b = a.split('/', 1)
|
||||||
if b is None:
|
elif b is None:
|
||||||
b = a
|
b = a
|
||||||
return super().__new__(cls, CsvInt(a), CsvInt(b))
|
return super().__new__(cls, CsvInt(a), CsvInt(b))
|
||||||
|
|
||||||
@@ -304,6 +306,9 @@ class CsvFrac(co.namedtuple('CsvFrac', 'a,b')):
|
|||||||
def __float__(self):
|
def __float__(self):
|
||||||
return float(self.a)
|
return float(self.a)
|
||||||
|
|
||||||
|
def __frac__(self):
|
||||||
|
return self.a, self.b
|
||||||
|
|
||||||
none = '%11s' % '-'
|
none = '%11s' % '-'
|
||||||
def table(self):
|
def table(self):
|
||||||
return '%11s' % (self,)
|
return '%11s' % (self,)
|
||||||
@@ -380,40 +385,182 @@ class CsvFrac(co.namedtuple('CsvFrac', 'a,b')):
|
|||||||
def __ge__(self, other):
|
def __ge__(self, other):
|
||||||
return not self.__lt__(other)
|
return not self.__lt__(other)
|
||||||
|
|
||||||
|
# fractional float fields, a/b
|
||||||
|
class CsvFfrac(co.namedtuple('CsvFfrac', 'a,b')):
|
||||||
|
__slots__ = ()
|
||||||
|
def __new__(cls, a=0, b=None):
|
||||||
|
if isinstance(a, CsvFfrac) and b is None:
|
||||||
|
return a
|
||||||
|
elif hasattr(a, '__frac__') and b is None:
|
||||||
|
a, b = a.__frac__()
|
||||||
|
elif isinstance(a, str) and b is None:
|
||||||
|
a, b = a.split('/', 1)
|
||||||
|
elif b is None:
|
||||||
|
b = a
|
||||||
|
return super().__new__(cls, CsvFloat(a), CsvFloat(b))
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return '%s(%r, %r)' % (self.__class__.__name__, self.a.a, self.b.a)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return '%s/%s' % (self.a, self.b)
|
||||||
|
|
||||||
|
def __csv__(self):
|
||||||
|
return '%s/%s' % (self.a.__csv__(), self.b.__csv__())
|
||||||
|
|
||||||
|
def __bool__(self):
|
||||||
|
return bool(self.a)
|
||||||
|
|
||||||
|
def __int__(self):
|
||||||
|
return int(self.a)
|
||||||
|
|
||||||
|
def __float__(self):
|
||||||
|
return float(self.a)
|
||||||
|
|
||||||
|
def __frac__(self):
|
||||||
|
return self.a, self.b
|
||||||
|
|
||||||
|
none = '%11s' % '-'
|
||||||
|
def table(self):
|
||||||
|
return '%11s' % (self,)
|
||||||
|
|
||||||
|
def notes(self):
|
||||||
|
if self.b.a == 0 and self.a.a == 0:
|
||||||
|
t = 1.0
|
||||||
|
elif self.b.a == 0:
|
||||||
|
t = mt.copysign(mt.inf, self.a.a)
|
||||||
|
else:
|
||||||
|
t = self.a.a / self.b.a
|
||||||
|
return ['∞%' if t == +mt.inf
|
||||||
|
else '-∞%' if t == -mt.inf
|
||||||
|
else '%.1f%%' % (100*t)]
|
||||||
|
|
||||||
|
def diff(self, other):
|
||||||
|
new_a, new_b = self if self else (CsvFloat(0), CsvFloat(0))
|
||||||
|
old_a, old_b = other if other else (CsvFloat(0), CsvFloat(0))
|
||||||
|
return '%11s' % ('%s/%s' % (
|
||||||
|
new_a.diff(old_a).strip(),
|
||||||
|
new_b.diff(old_b).strip()))
|
||||||
|
|
||||||
|
def ratio(self, other):
|
||||||
|
new_a, new_b = self if self else (CsvFloat(0), CsvFloat(0))
|
||||||
|
old_a, old_b = other if other else (CsvFloat(0), CsvFloat(0))
|
||||||
|
new = new_a.a/new_b.a if new_b.a else 1.0
|
||||||
|
old = old_a.a/old_b.a if old_b.a else 1.0
|
||||||
|
return new - old
|
||||||
|
|
||||||
|
def __pos__(self):
|
||||||
|
return self.__class__(+self.a, +self.b)
|
||||||
|
|
||||||
|
def __neg__(self):
|
||||||
|
return self.__class__(-self.a, -self.b)
|
||||||
|
|
||||||
|
def __abs__(self):
|
||||||
|
return self.__class__(abs(self.a), abs(self.b))
|
||||||
|
|
||||||
|
def __add__(self, other):
|
||||||
|
return self.__class__(self.a + other.a, self.b + other.b)
|
||||||
|
|
||||||
|
def __sub__(self, other):
|
||||||
|
return self.__class__(self.a - other.a, self.b - other.b)
|
||||||
|
|
||||||
|
def __mul__(self, other):
|
||||||
|
return self.__class__(self.a * other.a, self.b * other.b)
|
||||||
|
|
||||||
|
def __truediv__(self, other):
|
||||||
|
return self.__class__(self.a / other.a, self.b / other.b)
|
||||||
|
|
||||||
|
def __mod__(self, other):
|
||||||
|
return self.__class__(self.a % other.a, self.b % other.b)
|
||||||
|
|
||||||
|
def __hash__(self):
|
||||||
|
return super().__hash__()
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return super().__eq__(other)
|
||||||
|
|
||||||
|
def __ne__(self, other):
|
||||||
|
return not self.__eq__(other)
|
||||||
|
|
||||||
|
def __lt__(self, other):
|
||||||
|
self_a, self_b = self if self.b.a else (CsvFloat(1), CsvFloat(1))
|
||||||
|
other_a, other_b = other if other.b.a else (CsvFloat(1), CsvFloat(1))
|
||||||
|
return self_a * other_b < other_a * self_b
|
||||||
|
|
||||||
|
def __gt__(self, other):
|
||||||
|
return self.__class__.__lt__(other, self)
|
||||||
|
|
||||||
|
def __le__(self, other):
|
||||||
|
return not self.__gt__(other)
|
||||||
|
|
||||||
|
def __ge__(self, other):
|
||||||
|
return not self.__lt__(other)
|
||||||
|
|
||||||
|
|
||||||
# various fold operations
|
# various fold operations
|
||||||
class CsvSum:
|
class CsvFold:
|
||||||
|
def type(self, type):
|
||||||
|
return type
|
||||||
|
|
||||||
|
def __call__(self, xs):
|
||||||
|
assert False
|
||||||
|
|
||||||
|
class CsvSum(CsvFold):
|
||||||
def __call__(self, xs):
|
def __call__(self, xs):
|
||||||
return sum(xs[1:], start=xs[0])
|
return sum(xs[1:], start=xs[0])
|
||||||
|
|
||||||
class CsvProd:
|
class CsvProd(CsvFold):
|
||||||
def __call__(self, xs):
|
def __call__(self, xs):
|
||||||
return mt.prod(xs[1:], start=xs[0])
|
return mt.prod(xs[1:], start=xs[0])
|
||||||
|
|
||||||
class CsvMin:
|
class CsvMin(CsvFold):
|
||||||
def __call__(self, xs):
|
def __call__(self, xs):
|
||||||
return min(xs)
|
return min(xs)
|
||||||
|
|
||||||
class CsvMax:
|
class CsvMax(CsvFold):
|
||||||
def __call__(self, xs):
|
def __call__(self, xs):
|
||||||
return max(xs)
|
return max(xs)
|
||||||
|
|
||||||
class CsvAvg:
|
class CsvAvg(CsvFold):
|
||||||
|
def type(self, t):
|
||||||
|
return CsvFfrac if hasattr(t, '__frac__') else CsvFloat
|
||||||
|
|
||||||
def __call__(self, xs):
|
def __call__(self, xs):
|
||||||
|
if hasattr(xs[0], '__frac__'):
|
||||||
|
return CsvFfrac(self([x.a for x in xs]), self([x.b for x in xs]))
|
||||||
|
|
||||||
return CsvFloat(sum(float(x) for x in xs) / len(xs))
|
return CsvFloat(sum(float(x) for x in xs) / len(xs))
|
||||||
|
|
||||||
class CsvStddev:
|
class CsvStddev(CsvFold):
|
||||||
|
def type(self, t):
|
||||||
|
return CsvFfrac if hasattr(t, '__frac__') else CsvFloat
|
||||||
|
|
||||||
def __call__(self, xs):
|
def __call__(self, xs):
|
||||||
|
if hasattr(xs[0], '__frac__'):
|
||||||
|
return CsvFfrac(self([x.a for x in xs]), self([x.b for x in xs]))
|
||||||
|
|
||||||
avg = sum(float(x) for x in xs) / len(xs)
|
avg = sum(float(x) for x in xs) / len(xs)
|
||||||
return CsvFloat(mt.sqrt(
|
return CsvFloat(mt.sqrt(
|
||||||
sum((float(x) - avg)**2 for x in xs) / len(xs)))
|
sum((float(x) - avg)**2 for x in xs) / len(xs)))
|
||||||
|
|
||||||
class CsvGMean:
|
class CsvGMean(CsvFold):
|
||||||
|
def type(self, t):
|
||||||
|
return CsvFfrac if hasattr(t, '__frac__') else CsvFloat
|
||||||
|
|
||||||
def __call__(self, xs):
|
def __call__(self, xs):
|
||||||
|
if hasattr(xs[0], '__frac__'):
|
||||||
|
return CsvFfrac(self([x.a for x in xs]), self([x.b for x in xs]))
|
||||||
|
|
||||||
return CsvFloat(mt.prod(float(x) for x in xs)**(1/len(xs)))
|
return CsvFloat(mt.prod(float(x) for x in xs)**(1/len(xs)))
|
||||||
|
|
||||||
class CsvGStddev:
|
class CsvGStddev(CsvFold):
|
||||||
|
def type(self, t):
|
||||||
|
return CsvFfrac if hasattr(t, '__frac__') else CsvFloat
|
||||||
|
|
||||||
def __call__(self, xs):
|
def __call__(self, xs):
|
||||||
|
if hasattr(xs[0], '__frac__'):
|
||||||
|
return CsvFfrac(self([x.a for x in xs]), self([x.b for x in xs]))
|
||||||
|
|
||||||
gmean = mt.prod(float(x) for x in xs)**(1/len(xs))
|
gmean = mt.prod(float(x) for x in xs)**(1/len(xs))
|
||||||
return CsvFloat(
|
return CsvFloat(
|
||||||
mt.exp(mt.sqrt(
|
mt.exp(mt.sqrt(
|
||||||
@@ -554,7 +701,7 @@ class CsvExpr:
|
|||||||
return CsvInt
|
return CsvInt
|
||||||
|
|
||||||
def fold(self, types={}):
|
def fold(self, types={}):
|
||||||
return CsvSum, None
|
return CsvSum
|
||||||
|
|
||||||
def eval(self, fields={}, state=None):
|
def eval(self, fields={}, state=None):
|
||||||
return self.a
|
return self.a
|
||||||
@@ -567,7 +714,7 @@ class CsvExpr:
|
|||||||
return CsvFloat
|
return CsvFloat
|
||||||
|
|
||||||
def fold(self, types={}):
|
def fold(self, types={}):
|
||||||
return CsvSum, None
|
return CsvSum
|
||||||
|
|
||||||
def eval(self, fields={}, state=None):
|
def eval(self, fields={}, state=None):
|
||||||
return self.a
|
return self.a
|
||||||
@@ -585,7 +732,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, None
|
return CsvSum
|
||||||
|
|
||||||
def eval(self, fields={}, state=None):
|
def eval(self, fields={}, state=None):
|
||||||
if self.a not in fields:
|
if self.a not in fields:
|
||||||
@@ -611,6 +758,7 @@ class CsvExpr:
|
|||||||
class Int(Expr):
|
class Int(Expr):
|
||||||
"""Convert to an integer"""
|
"""Convert to an integer"""
|
||||||
def type(self, types={}):
|
def type(self, types={}):
|
||||||
|
super().type(types)
|
||||||
return CsvInt
|
return CsvInt
|
||||||
|
|
||||||
def eval(self, fields={}, state=None):
|
def eval(self, fields={}, state=None):
|
||||||
@@ -620,6 +768,7 @@ class CsvExpr:
|
|||||||
class Float(Expr):
|
class Float(Expr):
|
||||||
"""Convert to a float"""
|
"""Convert to a float"""
|
||||||
def type(self, types={}):
|
def type(self, types={}):
|
||||||
|
super().type(types)
|
||||||
return CsvFloat
|
return CsvFloat
|
||||||
|
|
||||||
def eval(self, fields={}, state=None):
|
def eval(self, fields={}, state=None):
|
||||||
@@ -629,6 +778,9 @@ class CsvExpr:
|
|||||||
class Frac(Expr):
|
class Frac(Expr):
|
||||||
"""Convert to a fraction"""
|
"""Convert to a fraction"""
|
||||||
def type(self, types={}):
|
def type(self, types={}):
|
||||||
|
self.a.type(types)
|
||||||
|
if len(self) > 1:
|
||||||
|
self.b.type(types)
|
||||||
return CsvFrac
|
return CsvFrac
|
||||||
|
|
||||||
def eval(self, fields={}, state=None):
|
def eval(self, fields={}, state=None):
|
||||||
@@ -640,13 +792,31 @@ class CsvExpr:
|
|||||||
self.a.eval(fields, state),
|
self.a.eval(fields, state),
|
||||||
self.b.eval(fields, state))
|
self.b.eval(fields, state))
|
||||||
|
|
||||||
|
@func('ffrac', 'a[, b]')
|
||||||
|
class Ffrac(Expr):
|
||||||
|
"""Convert to a float fraction"""
|
||||||
|
def type(self, types={}):
|
||||||
|
self.a.type(types)
|
||||||
|
if len(self) > 1:
|
||||||
|
self.b.type(types)
|
||||||
|
return CsvFfrac
|
||||||
|
|
||||||
|
def eval(self, fields={}, state=None):
|
||||||
|
if len(self) == 1:
|
||||||
|
return CsvFfrac(
|
||||||
|
self.a.eval(fields, state))
|
||||||
|
else:
|
||||||
|
return CsvFfrac(
|
||||||
|
self.a.eval(fields, state),
|
||||||
|
self.b.eval(fields, state))
|
||||||
|
|
||||||
# fold exprs
|
# fold exprs
|
||||||
@func('sum', 'a[, ...]')
|
@func('sum', 'a[, ...]')
|
||||||
class Sum(Expr):
|
class Sum(Expr):
|
||||||
"""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, None
|
return CsvSum
|
||||||
else:
|
else:
|
||||||
return self.a.fold(types)
|
return self.a.fold(types)
|
||||||
|
|
||||||
@@ -661,7 +831,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, None
|
return Prod
|
||||||
else:
|
else:
|
||||||
return self.a.fold(types)
|
return self.a.fold(types)
|
||||||
|
|
||||||
@@ -676,7 +846,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, None
|
return CsvMin
|
||||||
else:
|
else:
|
||||||
return self.a.fold(types)
|
return self.a.fold(types)
|
||||||
|
|
||||||
@@ -691,7 +861,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, None
|
return CsvMax
|
||||||
else:
|
else:
|
||||||
return self.a.fold(types)
|
return self.a.fold(types)
|
||||||
|
|
||||||
@@ -705,14 +875,15 @@ class CsvExpr:
|
|||||||
class Avg(Expr):
|
class Avg(Expr):
|
||||||
"""Find the average of this column or fields"""
|
"""Find the average of this column or fields"""
|
||||||
def type(self, types={}):
|
def type(self, types={}):
|
||||||
|
t = super().type(types)
|
||||||
if len(self) == 1:
|
if len(self) == 1:
|
||||||
return self.a.type(types)
|
return t
|
||||||
else:
|
else:
|
||||||
return CsvFloat
|
return CsvFfrac if hasattr(t, '__frac__') else CsvFloat
|
||||||
|
|
||||||
def fold(self, types={}):
|
def fold(self, types={}):
|
||||||
if len(self) == 1:
|
if len(self) == 1:
|
||||||
return CsvAvg, CsvFloat
|
return CsvAvg
|
||||||
else:
|
else:
|
||||||
return self.a.fold(types)
|
return self.a.fold(types)
|
||||||
|
|
||||||
@@ -726,14 +897,15 @@ class CsvExpr:
|
|||||||
class Stddev(Expr):
|
class Stddev(Expr):
|
||||||
"""Find the standard deviation of this column or fields"""
|
"""Find the standard deviation of this column or fields"""
|
||||||
def type(self, types={}):
|
def type(self, types={}):
|
||||||
|
t = super().type(types)
|
||||||
if len(self) == 1:
|
if len(self) == 1:
|
||||||
return self.a.type(types)
|
return t
|
||||||
else:
|
else:
|
||||||
return CsvFloat
|
return CsvFfrac if hasattr(t, '__frac__') else CsvFloat
|
||||||
|
|
||||||
def fold(self, types={}):
|
def fold(self, types={}):
|
||||||
if len(self) == 1:
|
if len(self) == 1:
|
||||||
return CsvStddev, CsvFloat
|
return CsvStddev
|
||||||
else:
|
else:
|
||||||
return self.a.fold(types)
|
return self.a.fold(types)
|
||||||
|
|
||||||
@@ -747,14 +919,15 @@ class CsvExpr:
|
|||||||
class GMean(Expr):
|
class GMean(Expr):
|
||||||
"""Find the geometric mean of this column or fields"""
|
"""Find the geometric mean of this column or fields"""
|
||||||
def type(self, types={}):
|
def type(self, types={}):
|
||||||
|
t = super().type(types)
|
||||||
if len(self) == 1:
|
if len(self) == 1:
|
||||||
return self.a.type(types)
|
return t
|
||||||
else:
|
else:
|
||||||
return CsvFloat
|
return CsvFfrac if hasattr(t, '__frac__') else CsvFloat
|
||||||
|
|
||||||
def fold(self, types={}):
|
def fold(self, types={}):
|
||||||
if len(self) == 1:
|
if len(self) == 1:
|
||||||
return CsvGMean, CsvFloat
|
return CsvGMean
|
||||||
else:
|
else:
|
||||||
return self.a.fold(types)
|
return self.a.fold(types)
|
||||||
|
|
||||||
@@ -768,14 +941,15 @@ class CsvExpr:
|
|||||||
class GStddev(Expr):
|
class GStddev(Expr):
|
||||||
"""Find the geometric stddev of this column or fields"""
|
"""Find the geometric stddev of this column or fields"""
|
||||||
def type(self, types={}):
|
def type(self, types={}):
|
||||||
|
t = super().type(types)
|
||||||
if len(self) == 1:
|
if len(self) == 1:
|
||||||
return self.a.type(types)
|
return t
|
||||||
else:
|
else:
|
||||||
return CsvFloat
|
return CsvFfrac if hasattr(t, '__frac__') else CsvFloat
|
||||||
|
|
||||||
def fold(self, types={}):
|
def fold(self, types={}):
|
||||||
if len(self) == 1:
|
if len(self) == 1:
|
||||||
return CsvGStddev, CsvFloat
|
return CsvGStddev
|
||||||
else:
|
else:
|
||||||
return self.a.fold(types)
|
return self.a.fold(types)
|
||||||
|
|
||||||
@@ -802,7 +976,7 @@ class CsvExpr:
|
|||||||
|
|
||||||
def fold(self, types={}):
|
def fold(self, types={}):
|
||||||
# don't typecheck by fields
|
# don't typecheck by fields
|
||||||
return CsvSum, None
|
return CsvSum
|
||||||
|
|
||||||
def eval(self, fields={}, state=None):
|
def eval(self, fields={}, state=None):
|
||||||
if state is None:
|
if state is None:
|
||||||
@@ -897,13 +1071,16 @@ class CsvExpr:
|
|||||||
class Ratio(Expr):
|
class Ratio(Expr):
|
||||||
"""Ratio of a fraction as a float"""
|
"""Ratio of a fraction as a float"""
|
||||||
def type(self, types={}):
|
def type(self, types={}):
|
||||||
|
super().type(types)
|
||||||
return CsvFloat
|
return CsvFloat
|
||||||
|
|
||||||
def eval(self, fields={}, state=None):
|
def eval(self, fields={}, state=None):
|
||||||
v = CsvFrac(self.a.eval(fields, state))
|
v = self.a.eval(fields, state)
|
||||||
if not float(v.b) and not float(v.a):
|
if not hasattr(v, '__frac__'):
|
||||||
|
return CsvFloat(1) # emulates cast + eval
|
||||||
|
elif not v.b and not v.a:
|
||||||
return CsvFloat(1)
|
return CsvFloat(1)
|
||||||
elif not float(v.b):
|
elif not v.b:
|
||||||
return CsvFloat(mt.copysign(mt.inf, float(v.a)))
|
return CsvFloat(mt.copysign(mt.inf, float(v.a)))
|
||||||
else:
|
else:
|
||||||
return CsvFloat(float(v.a) / float(v.b))
|
return CsvFloat(float(v.a) / float(v.b))
|
||||||
@@ -912,10 +1089,15 @@ class CsvExpr:
|
|||||||
class Total(Expr):
|
class Total(Expr):
|
||||||
"""Total part of a fraction"""
|
"""Total part of a fraction"""
|
||||||
def type(self, types={}):
|
def type(self, types={}):
|
||||||
return CsvInt
|
t = super().type(types)
|
||||||
|
return CsvFloat if t in {CsvFloat, CsvFfrac} else CsvInt
|
||||||
|
|
||||||
def eval(self, fields={}, state=None):
|
def eval(self, fields={}, state=None):
|
||||||
return CsvFrac(self.a.eval(fields, state)).b
|
v = self.a.eval(fields, state)
|
||||||
|
if not hasattr(v, '__frac__'):
|
||||||
|
return v # emulates cast + eval
|
||||||
|
else:
|
||||||
|
return v.b
|
||||||
|
|
||||||
@func('abs', 'a')
|
@func('abs', 'a')
|
||||||
class Abs(Expr):
|
class Abs(Expr):
|
||||||
@@ -927,63 +1109,107 @@ class CsvExpr:
|
|||||||
class Ceil(Expr):
|
class Ceil(Expr):
|
||||||
"""Round up to nearest integer"""
|
"""Round up to nearest integer"""
|
||||||
def type(self, types={}):
|
def type(self, types={}):
|
||||||
return CsvFloat
|
t = super().type(types)
|
||||||
|
return CsvFfrac if hasattr(t, '__frac__') else CsvFloat
|
||||||
|
|
||||||
def eval(self, fields={}, state=None):
|
def eval(self, fields={}, state=None):
|
||||||
return CsvFloat(mt.ceil(float(self.a.eval(fields, state))))
|
v = self.a.eval(fields, state)
|
||||||
|
if hasattr(v, '__frac__'):
|
||||||
|
return CsvFfrac(mt.ceil(float(v.a)), mt.ceil(float(v.b)))
|
||||||
|
else:
|
||||||
|
return CsvFloat(mt.ceil(float(v)))
|
||||||
|
|
||||||
@func('floor', 'a')
|
@func('floor', 'a')
|
||||||
class Floor(Expr):
|
class Floor(Expr):
|
||||||
"""Round down to nearest integer"""
|
"""Round down to nearest integer"""
|
||||||
def type(self, types={}):
|
def type(self, types={}):
|
||||||
return CsvFloat
|
t = super().type(types)
|
||||||
|
return CsvFfrac if hasattr(t, '__frac__') else CsvFloat
|
||||||
|
|
||||||
def eval(self, fields={}, state=None):
|
def eval(self, fields={}, state=None):
|
||||||
return CsvFloat(mt.floor(float(self.a.eval(fields, state))))
|
v = self.a.eval(fields, state)
|
||||||
|
if hasattr(v, '__frac__'):
|
||||||
|
return CsvFfrac(mt.floor(float(v.a)), mt.floor(float(v.b)))
|
||||||
|
else:
|
||||||
|
return CsvFloat(mt.floor(float(v)))
|
||||||
|
|
||||||
@func('log', 'a[, b]')
|
@func('log', 'a[, b]')
|
||||||
class Log(Expr):
|
class Log(Expr):
|
||||||
"""Log of a with base e, or log of a with base b"""
|
"""Log of a with base e, or log of a with base b"""
|
||||||
def type(self, types={}):
|
def type(self, types={}):
|
||||||
return CsvFloat
|
t = self.a.type(types)
|
||||||
|
if len(self) > 1:
|
||||||
|
self.b.type(types)
|
||||||
|
return CsvFfrac if hasattr(t, '__frac__') else CsvFloat
|
||||||
|
|
||||||
def eval(self, fields={}, state=None):
|
def eval(self, fields={}, state=None):
|
||||||
|
v = self.a.eval(fields, state)
|
||||||
if len(self) == 1:
|
if len(self) == 1:
|
||||||
return CsvFloat(mt.log(
|
if hasattr(v, '__frac__'):
|
||||||
float(self.a.eval(fields, state))))
|
return CsvFfrac(
|
||||||
|
mt.log(float(v.a)),
|
||||||
|
mt.log(float(v.b)))
|
||||||
|
else:
|
||||||
|
return CsvFloat(
|
||||||
|
mt.log(float(v)))
|
||||||
else:
|
else:
|
||||||
return CsvFloat(mt.log(
|
e = float(self.b.eval(fields, state))
|
||||||
float(self.a.eval(fields, state)),
|
if hasattr(v, '__frac__'):
|
||||||
float(self.b.eval(fields, state))))
|
return CsvFfrac(
|
||||||
|
mt.log(float(v.a), e),
|
||||||
|
mt.log(float(v.b), e))
|
||||||
|
else:
|
||||||
|
return CsvFloat(
|
||||||
|
mt.log(float(v), e))
|
||||||
|
|
||||||
@func('pow', 'a[, b]')
|
@func('pow', 'a[, b]')
|
||||||
class Pow(Expr):
|
class Pow(Expr):
|
||||||
"""e to the power of a, or a to the power of b"""
|
"""e to the power of a, or a to the power of b"""
|
||||||
def type(self, types={}):
|
def type(self, types={}):
|
||||||
return CsvFloat
|
t = self.a.type(types)
|
||||||
|
if len(self) > 1:
|
||||||
|
self.b.type(types)
|
||||||
|
return CsvFfrac if hasattr(t, '__frac__') else CsvFloat
|
||||||
|
|
||||||
def eval(self, fields={}, state=None):
|
def eval(self, fields={}, state=None):
|
||||||
|
v = self.a.eval(fields, state)
|
||||||
if len(self) == 1:
|
if len(self) == 1:
|
||||||
return CsvFloat(mt.exp(
|
if hasattr(v, '__frac__'):
|
||||||
float(self.a.eval(fields, state))))
|
return CsvFfrac(
|
||||||
|
mt.exp(float(v.a)),
|
||||||
|
mt.exp(float(v.b)))
|
||||||
|
else:
|
||||||
|
return CsvFloat(
|
||||||
|
mt.exp(float(v)))
|
||||||
else:
|
else:
|
||||||
return CsvFloat(mt.pow(
|
e = float(self.b.eval(fields, state))
|
||||||
float(self.a.eval(fields, state)),
|
if hasattr(v, '__frac__'):
|
||||||
float(self.b.eval(fields, state))))
|
return CsvFfrac(
|
||||||
|
mt.pow(float(v.a), e),
|
||||||
|
mt.pow(float(v.b), e))
|
||||||
|
else:
|
||||||
|
return CsvFloat(
|
||||||
|
mt.pow(float(v), e))
|
||||||
|
|
||||||
@func('sqrt', 'a')
|
@func('sqrt', 'a')
|
||||||
class Sqrt(Expr):
|
class Sqrt(Expr):
|
||||||
"""Square root"""
|
"""Square root"""
|
||||||
def type(self, types={}):
|
def type(self, types={}):
|
||||||
return CsvFloat
|
t = super().type(types)
|
||||||
|
return CsvFfrac if hasattr(t, '__frac__') else CsvFloat
|
||||||
|
|
||||||
def eval(self, fields={}, state=None):
|
def eval(self, fields={}, state=None):
|
||||||
return CsvFloat(mt.sqrt(float(self.a.eval(fields, state))))
|
v = self.a.eval(fields, state)
|
||||||
|
if hasattr(v, '__frac__'):
|
||||||
|
return CsvFfrac(mt.sqrt(float(v.a)), mt.sqrt(float(v.b)))
|
||||||
|
else:
|
||||||
|
return CsvFloat(mt.sqrt(float(v)))
|
||||||
|
|
||||||
@func('isint', 'a')
|
@func('isint', 'a')
|
||||||
class IsInt(Expr):
|
class IsInt(Expr):
|
||||||
"""1 if a is an integer, otherwise 0"""
|
"""1 if a is an integer, otherwise 0"""
|
||||||
def type(self, types={}):
|
def type(self, types={}):
|
||||||
|
super().type(types)
|
||||||
return CsvInt
|
return CsvInt
|
||||||
|
|
||||||
def eval(self, fields={}, state=None):
|
def eval(self, fields={}, state=None):
|
||||||
@@ -996,6 +1222,7 @@ class CsvExpr:
|
|||||||
class IsFloat(Expr):
|
class IsFloat(Expr):
|
||||||
"""1 if a is a float, otherwise 0"""
|
"""1 if a is a float, otherwise 0"""
|
||||||
def type(self, types={}):
|
def type(self, types={}):
|
||||||
|
super().type(types)
|
||||||
return CsvInt
|
return CsvInt
|
||||||
|
|
||||||
def eval(self, fields={}, state=None):
|
def eval(self, fields={}, state=None):
|
||||||
@@ -1008,6 +1235,7 @@ class CsvExpr:
|
|||||||
class IsFrac(Expr):
|
class IsFrac(Expr):
|
||||||
"""1 if a is a fraction, otherwise 0"""
|
"""1 if a is a fraction, otherwise 0"""
|
||||||
def type(self, types={}):
|
def type(self, types={}):
|
||||||
|
super().type(types)
|
||||||
return CsvInt
|
return CsvInt
|
||||||
|
|
||||||
def eval(self, fields={}, state=None):
|
def eval(self, fields={}, state=None):
|
||||||
@@ -1016,10 +1244,24 @@ class CsvExpr:
|
|||||||
else:
|
else:
|
||||||
return CsvInt(0)
|
return CsvInt(0)
|
||||||
|
|
||||||
|
@func('isffrac', 'a')
|
||||||
|
class IsFfrac(Expr):
|
||||||
|
"""1 if a is a fraction, otherwise 0"""
|
||||||
|
def type(self, types={}):
|
||||||
|
super().type(types)
|
||||||
|
return CsvInt
|
||||||
|
|
||||||
|
def eval(self, fields={}, state=None):
|
||||||
|
if isinstance(self.a.eval(fields, state), CsvFfrac):
|
||||||
|
return CsvInt(1)
|
||||||
|
else:
|
||||||
|
return CsvInt(0)
|
||||||
|
|
||||||
@func('isinf', 'a')
|
@func('isinf', 'a')
|
||||||
class IsInf(Expr):
|
class IsInf(Expr):
|
||||||
"""1 if a is infinite, otherwise 0"""
|
"""1 if a is infinite, otherwise 0"""
|
||||||
def type(self, types={}):
|
def type(self, types={}):
|
||||||
|
super().type(types)
|
||||||
return CsvInt
|
return CsvInt
|
||||||
|
|
||||||
def eval(self, fields={}, state=None):
|
def eval(self, fields={}, state=None):
|
||||||
@@ -1032,6 +1274,7 @@ class CsvExpr:
|
|||||||
class IsNan(Expr):
|
class IsNan(Expr):
|
||||||
"""1 if a is a NAN, otherwise 0"""
|
"""1 if a is a NAN, otherwise 0"""
|
||||||
def type(self, types={}):
|
def type(self, types={}):
|
||||||
|
super().type(types)
|
||||||
return CsvInt
|
return CsvInt
|
||||||
|
|
||||||
def eval(self, fields={}, state=None):
|
def eval(self, fields={}, state=None):
|
||||||
@@ -1070,6 +1313,7 @@ class CsvExpr:
|
|||||||
class NotNot(Expr):
|
class NotNot(Expr):
|
||||||
"""1 if a is zero, otherwise 0"""
|
"""1 if a is zero, otherwise 0"""
|
||||||
def type(self, types={}):
|
def type(self, types={}):
|
||||||
|
super().type(types)
|
||||||
return CsvInt
|
return CsvInt
|
||||||
|
|
||||||
def eval(self, fields={}, state=None):
|
def eval(self, fields={}, state=None):
|
||||||
@@ -1128,6 +1372,10 @@ class CsvExpr:
|
|||||||
@bop('==', 4)
|
@bop('==', 4)
|
||||||
class Eq(Expr):
|
class Eq(Expr):
|
||||||
"""1 if a equals b, otherwise 0"""
|
"""1 if a equals b, otherwise 0"""
|
||||||
|
def type(self, types={}):
|
||||||
|
super().type(types)
|
||||||
|
return CsvInt
|
||||||
|
|
||||||
def eval(self, fields={}, state=None):
|
def eval(self, fields={}, state=None):
|
||||||
if self.a.eval(fields, state) == self.b.eval(fields, state):
|
if self.a.eval(fields, state) == self.b.eval(fields, state):
|
||||||
return CsvInt(1)
|
return CsvInt(1)
|
||||||
@@ -1137,6 +1385,10 @@ class CsvExpr:
|
|||||||
@bop('!=', 4)
|
@bop('!=', 4)
|
||||||
class Ne(Expr):
|
class Ne(Expr):
|
||||||
"""1 if a does not equal b, otherwise 0"""
|
"""1 if a does not equal b, otherwise 0"""
|
||||||
|
def type(self, types={}):
|
||||||
|
super().type(types)
|
||||||
|
return CsvInt
|
||||||
|
|
||||||
def eval(self, fields={}, state=None):
|
def eval(self, fields={}, state=None):
|
||||||
if self.a.eval(fields, state) != self.b.eval(fields, state):
|
if self.a.eval(fields, state) != self.b.eval(fields, state):
|
||||||
return CsvInt(1)
|
return CsvInt(1)
|
||||||
@@ -1146,6 +1398,10 @@ class CsvExpr:
|
|||||||
@bop('<', 4)
|
@bop('<', 4)
|
||||||
class Lt(Expr):
|
class Lt(Expr):
|
||||||
"""1 if a is less than b"""
|
"""1 if a is less than b"""
|
||||||
|
def type(self, types={}):
|
||||||
|
super().type(types)
|
||||||
|
return CsvInt
|
||||||
|
|
||||||
def eval(self, fields={}, state=None):
|
def eval(self, fields={}, state=None):
|
||||||
if self.a.eval(fields, state) < self.b.eval(fields, state):
|
if self.a.eval(fields, state) < self.b.eval(fields, state):
|
||||||
return CsvInt(1)
|
return CsvInt(1)
|
||||||
@@ -1155,6 +1411,10 @@ class CsvExpr:
|
|||||||
@bop('<=', 4)
|
@bop('<=', 4)
|
||||||
class Le(Expr):
|
class Le(Expr):
|
||||||
"""1 if a is less than or equal to b"""
|
"""1 if a is less than or equal to b"""
|
||||||
|
def type(self, types={}):
|
||||||
|
super().type(types)
|
||||||
|
return CsvInt
|
||||||
|
|
||||||
def eval(self, fields={}, state=None):
|
def eval(self, fields={}, state=None):
|
||||||
if self.a.eval(fields, state) <= self.b.eval(fields, state):
|
if self.a.eval(fields, state) <= self.b.eval(fields, state):
|
||||||
return CsvInt(1)
|
return CsvInt(1)
|
||||||
@@ -1164,6 +1424,10 @@ class CsvExpr:
|
|||||||
@bop('>', 4)
|
@bop('>', 4)
|
||||||
class Gt(Expr):
|
class Gt(Expr):
|
||||||
"""1 if a is greater than b"""
|
"""1 if a is greater than b"""
|
||||||
|
def type(self, types={}):
|
||||||
|
super().type(types)
|
||||||
|
return CsvInt
|
||||||
|
|
||||||
def eval(self, fields={}, state=None):
|
def eval(self, fields={}, state=None):
|
||||||
if self.a.eval(fields, state) > self.b.eval(fields, state):
|
if self.a.eval(fields, state) > self.b.eval(fields, state):
|
||||||
return CsvInt(1)
|
return CsvInt(1)
|
||||||
@@ -1173,6 +1437,10 @@ class CsvExpr:
|
|||||||
@bop('>=', 4)
|
@bop('>=', 4)
|
||||||
class Ge(Expr):
|
class Ge(Expr):
|
||||||
"""1 if a is greater than or equal to b"""
|
"""1 if a is greater than or equal to b"""
|
||||||
|
def type(self, types={}):
|
||||||
|
super().type(types)
|
||||||
|
return CsvInt
|
||||||
|
|
||||||
def eval(self, fields={}, state=None):
|
def eval(self, fields={}, state=None):
|
||||||
if self.a.eval(fields, state) >= self.b.eval(fields, state):
|
if self.a.eval(fields, state) >= self.b.eval(fields, state):
|
||||||
return CsvInt(1)
|
return CsvInt(1)
|
||||||
@@ -1661,7 +1929,7 @@ def compile(fields_, results,
|
|||||||
file=sys.stderr)
|
file=sys.stderr)
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
|
|
||||||
for t in [CsvInt, CsvFloat, CsvFrac]:
|
for t in [CsvInt, CsvFloat, CsvFrac, CsvFfrac]:
|
||||||
for r in results:
|
for r in results:
|
||||||
if k in r and r[k].strip():
|
if k in r and r[k].strip():
|
||||||
try:
|
try:
|
||||||
@@ -1683,11 +1951,12 @@ def compile(fields_, results,
|
|||||||
types___[k] = expr.type(types__)
|
types___[k] = expr.type(types__)
|
||||||
|
|
||||||
# foldcheck field exprs
|
# foldcheck field exprs
|
||||||
folds___ = {k: (CsvSum, t) for k, v in types__.items()}
|
folds___ = {k: CsvSum 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__)
|
||||||
# instantiate folds and resolve fold types
|
# instantiate folds and resolve fold types
|
||||||
folds___ = {k: (f(), t or types___[k]) for k, (f, t) in folds___.items()}
|
folds___ = {k: f() for k, f in folds___.items()}
|
||||||
|
folds___ = {k: (f, f.type(types___[k])) for k, f in folds___.items()}
|
||||||
|
|
||||||
# create result class
|
# create result class
|
||||||
def __new__(cls, _state=None, **r):
|
def __new__(cls, _state=None, **r):
|
||||||
@@ -2410,7 +2679,7 @@ def list_fields(csv_paths, **args):
|
|||||||
types_ = {}
|
types_ = {}
|
||||||
for k in fields_:
|
for k in fields_:
|
||||||
try:
|
try:
|
||||||
for t in [CsvInt, CsvFloat, CsvFrac]:
|
for t in [CsvInt, CsvFloat, CsvFrac, CsvFfrac]:
|
||||||
for r in results:
|
for r in results:
|
||||||
if k in r and r[k].strip():
|
if k in r and r[k].strip():
|
||||||
try:
|
try:
|
||||||
@@ -2466,7 +2735,7 @@ def list_computed(fields_, results, Result, **args):
|
|||||||
types_ = {}
|
types_ = {}
|
||||||
for k in fields_:
|
for k in fields_:
|
||||||
try:
|
try:
|
||||||
for t in [CsvInt, CsvFloat, CsvFrac]:
|
for t in [CsvInt, CsvFloat, CsvFrac, CsvFfrac]:
|
||||||
for r in results:
|
for r in results:
|
||||||
if k in r and r[k].strip():
|
if k in r and r[k].strip():
|
||||||
try:
|
try:
|
||||||
|
|||||||
+1
-1
@@ -36,7 +36,7 @@ class CsvInt(co.namedtuple('CsvInt', 'a')):
|
|||||||
def __new__(cls, a=0):
|
def __new__(cls, a=0):
|
||||||
if isinstance(a, CsvInt):
|
if isinstance(a, CsvInt):
|
||||||
return a
|
return a
|
||||||
if isinstance(a, str):
|
elif isinstance(a, str):
|
||||||
try:
|
try:
|
||||||
a = int(a, 0)
|
a = int(a, 0)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
|||||||
+1
-1
@@ -40,7 +40,7 @@ class CsvInt(co.namedtuple('CsvInt', 'a')):
|
|||||||
def __new__(cls, a=0):
|
def __new__(cls, a=0):
|
||||||
if isinstance(a, CsvInt):
|
if isinstance(a, CsvInt):
|
||||||
return a
|
return a
|
||||||
if isinstance(a, str):
|
elif isinstance(a, str):
|
||||||
try:
|
try:
|
||||||
a = int(a, 0)
|
a = int(a, 0)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
|||||||
+1
-1
@@ -50,7 +50,7 @@ class CsvInt(co.namedtuple('CsvInt', 'a')):
|
|||||||
def __new__(cls, a=0):
|
def __new__(cls, a=0):
|
||||||
if isinstance(a, CsvInt):
|
if isinstance(a, CsvInt):
|
||||||
return a
|
return a
|
||||||
if isinstance(a, str):
|
elif isinstance(a, str):
|
||||||
try:
|
try:
|
||||||
a = int(a, 0)
|
a = int(a, 0)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
|||||||
+1
-1
@@ -41,7 +41,7 @@ class CsvInt(co.namedtuple('CsvInt', 'a')):
|
|||||||
def __new__(cls, a=0):
|
def __new__(cls, a=0):
|
||||||
if isinstance(a, CsvInt):
|
if isinstance(a, CsvInt):
|
||||||
return a
|
return a
|
||||||
if isinstance(a, str):
|
elif isinstance(a, str):
|
||||||
try:
|
try:
|
||||||
a = int(a, 0)
|
a = int(a, 0)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
|||||||
+1
-1
@@ -36,7 +36,7 @@ class CsvInt(co.namedtuple('CsvInt', 'a')):
|
|||||||
def __new__(cls, a=0):
|
def __new__(cls, a=0):
|
||||||
if isinstance(a, CsvInt):
|
if isinstance(a, CsvInt):
|
||||||
return a
|
return a
|
||||||
if isinstance(a, str):
|
elif isinstance(a, str):
|
||||||
try:
|
try:
|
||||||
a = int(a, 0)
|
a = int(a, 0)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
|||||||
+1
-1
@@ -36,7 +36,7 @@ class CsvInt(co.namedtuple('CsvInt', 'a')):
|
|||||||
def __new__(cls, a=0):
|
def __new__(cls, a=0):
|
||||||
if isinstance(a, CsvInt):
|
if isinstance(a, CsvInt):
|
||||||
return a
|
return a
|
||||||
if isinstance(a, str):
|
elif isinstance(a, str):
|
||||||
try:
|
try:
|
||||||
a = int(a, 0)
|
a = int(a, 0)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
|||||||
Reference in New Issue
Block a user