def testInterfaces(self): rt = row_tuple.RowTuple(values=dict(foo="Foo", bar="Bar", car="Car"), ordered_columns=["car", "bar", "foo"]) self.assertEqual(len(rt), 3) self.assertEqual(counted.count(rt), 3) self.assertEqual(list(rt), ["Car", "Bar", "Foo"]) self.assertEqual(associative.select(rt, 2), "Foo") with self.assertRaises(KeyError): associative.select(rt, "foo") with self.assertRaises(KeyError): structured.resolve(rt, 2) self.assertEqual(structured.resolve(rt, "foo"), "Foo")
def solve_membership(expr, vars): # There is an expectation that "foo" in "foobar" will be true, and, # simultaneously, that "foo" in ["foobar"] will be false. This is how the # analogous operator works in Python, among other languages. Where this # mental model breaks down is around repeated values, because, in EFILTER, # there is no difference between a tuple of one value and the one value, # so that "foo" in ("foobar") is true, while "foo" in ("foobar", "bar") is # false and "foo" in ("foo", "bar") is again true. These semantics are a # little unfortunate, and it may be that, in the future, the in operator # is disallowed on repeated values to prevent ambiguity. needle = solve(expr.element, vars).value if repeated.isrepeating(needle): raise errors.EfilterError( root=expr.element, query=expr.source, message=("More than one value not allowed in the needle. " "Got %d values.") % counted.count(needle)) # We need to fall through to __solve_and_destructure_repeated to handle # row tuples correctly. haystack, isrepeating = __solve_and_destructure_repeated(expr.set, vars) # For non-repeated values just use the first (singleton) value. if not isrepeating: for straw in haystack: haystack = straw break if isinstance(haystack, six.string_types): return Result(needle in haystack, ()) # Repeated values of more than one value and collections behave the same. # There are no proper sets in EFILTER so O(N) is what we get. if isrepeating or isinstance(haystack, (tuple, list)): for straw in haystack: # We're all farmers here. if straw == needle: return Result(True, ()) return Result(False, ()) # If haystack is not a repeating value, but it is iterable then it must # have originated from outside EFILTER. Lets try to do the right thing and # delegate to Python. for straw in haystack: return Result(needle in straw, None) return Result(False, ())
def count(self): return counted.count(self.source)
raise NotImplementedError() @dispatch.polymorphic def resolve(associative, key): raise NotImplementedError() @dispatch.polymorphic def getkeys(associative): raise NotImplementedError() class IAssociative(protocol.Protocol): _protocol_functions = (select, resolve, getkeys) IAssociative.implement(for_type=dict, implementations={ select: lambda d, key: d.get(key), resolve: lambda d, key: d.get(key), getkeys: lambda d: d.iterkeys() }) IAssociative.implement(for_type=counted.ICounted, implementations={ select: lambda c, idx: c[idx], resolve: lambda c, idx: c[idx], getkeys: lambda c: xrange(counted.count(c)) })
def fold(self, chunk): return counted.count(chunk)
def fixture_len(self): with open(testlib.get_fixture_path(self.fixture_name), "r") as fd: return counted.count(repeated.lines(fd))
def testLines(self): lines = std_io.Lines()(testlib.get_fixture_path("names.txt")) self.assertEqual(counted.count(lines), 6) fd = lines.fd lines = None self.assertTrue(fd.closed)
def isrepeating(x): """Optional: Is x a repeated var AND does it have more than one value?""" return isinstance(x, IRepeated) and counted.count(x) > 1
key: The name to be reflected. Must be a member of 'associative_cls'. Returns: The type of 'name' or None. Invalid names should return None, whereas valid names with unknown type should return AnyType. """ raise NotImplementedError() @dispatch.multimethod def reflect_runtime_key(associative, key): return reflect_static_key(type(associative), key) class IAssociative(protocol.Protocol): _required_functions = (select,) _optional_functions = (reflect_runtime_key, reflect_static_key, getkeys_runtime, getkeys_static) IAssociative.implement(for_type=dict, implementations={ select: lambda d, key: d[key], getkeys_runtime: lambda d: d.keys()}) IAssociative.implement(for_type=counted.ICounted, implementations={ select: lambda c, idx: c[idx], getkeys_runtime: lambda c: six.moves.range(counted.count(c))})
def fold(self, chunk): return (sum(chunk), counted.count(chunk))
Returns: The type of 'name' or None. Invalid names should return None, whereas valid names with unknown type should return AnyType. """ raise NotImplementedError() @dispatch.multimethod def reflect_runtime_key(associative, key): return reflect_static_key(type(associative), key) class IAssociative(protocol.Protocol): _required_functions = (select,) _optional_functions = (reflect_runtime_key, reflect_static_key, getkeys_runtime, getkeys_static) IAssociative.implement(for_type=dict, implementations={ select: lambda d, key: d[key], getkeys_runtime: lambda d: d.keys()}) IAssociative.implement( for_types=(list, tuple), implementations={ select: lambda c, idx: c[idx], getkeys_runtime: lambda c: six.moves.range(counted.count(c))})
_required_functions = (select,) _optional_functions = (reflect_runtime_key, reflect_static_key, getkeys_runtime, getkeys_static) @dispatch.multimethod def isassociative(x): return isinstance(x, IAssociative) IAssociative.implement(for_type=dict, implementations={ select: lambda d, key: d[key], reflect_runtime_key: lambda x, k: x.get(k), getkeys_runtime: lambda d: list(d.keys())}) def IAssociative_select(c, idx): """Out of bound reference just returns None.""" try: return c[idx] except IndexError: return None IAssociative.implement( for_types=(list, tuple), implementations={ select: IAssociative_select, getkeys_runtime: lambda c: six.moves.range(counted.count(c))})
@dispatch.polymorphic def select(associative, key): raise NotImplementedError() @dispatch.polymorphic def resolve(associative, key): raise NotImplementedError() @dispatch.polymorphic def getkeys(associative): raise NotImplementedError() class IAssociative(protocol.Protocol): _protocol_functions = (select, resolve, getkeys) IAssociative.implement(for_type=dict, implementations={ select: lambda d, key: d.get(key), resolve: lambda d, key: d.get(key), getkeys: lambda d: d.iterkeys()}) IAssociative.implement(for_type=counted.ICounted, implementations={ select: lambda c, idx: c[idx], resolve: lambda c, idx: c[idx], getkeys: lambda c: xrange(counted.count(c))})
def testCSV(self): csv = std_io.CSV()(testlib.get_fixture_path("small.csv")) self.assertEqual(counted.count(csv), 7) fd = csv.source.fd csv = None self.assertTrue(fd.closed)
def __call__(self, chunk): return counted.count(chunk)
The type of 'name' or None. Invalid names should return None, whereas valid names with unknown type should return AnyType. """ raise NotImplementedError() @dispatch.multimethod def reflect_runtime_key(associative, key): return reflect_static_key(type(associative), key) class IAssociative(protocol.Protocol): _required_functions = (select, ) _optional_functions = (reflect_runtime_key, reflect_static_key, getkeys_runtime, getkeys_static) IAssociative.implement(for_type=dict, implementations={ select: lambda d, key: d[key], getkeys_runtime: lambda d: d.keys() }) IAssociative.implement(for_types=(list, tuple), implementations={ select: lambda c, idx: c[idx], getkeys_runtime: lambda c: six.moves.range(counted.count(c)) })
def __call__(self, x): return counted.count(x)