From 3a8cc83cbe465b798647b92357eff2d52454f3dc Mon Sep 17 00:00:00 2001 From: SoniEx2 Date: Sun, 16 Feb 2020 19:35:47 -0300 Subject: Squashed commit of the following: * Move things around a bit more * Add project structure details to HACKING.md * Create setup.py * Split off A Boneless Datastructure Language --- testing/test_abdl.py | 199 ----------------------------------------------- testing/test_examples.py | 26 ------- testing/test_ops_abdl.py | 161 -------------------------------------- 3 files changed, 386 deletions(-) delete mode 100644 testing/test_abdl.py delete mode 100644 testing/test_examples.py delete mode 100644 testing/test_ops_abdl.py (limited to 'testing') diff --git a/testing/test_abdl.py b/testing/test_abdl.py deleted file mode 100644 index 4f5241f..0000000 --- a/testing/test_abdl.py +++ /dev/null @@ -1,199 +0,0 @@ -# Tests abdl.py - -import abdl - -import hypothesis -import hypothesis.strategies as st - -import collections.abc - -import re - -import traceback - - -abdl.DeprecationError.enable_key_match_compat = False - -# use abdl's _pairs for consistency. -pairs = abdl._pairs - -# do not put integers, floats, etc here -# do not put bytes, they iterate as integers -hashables = st.deferred(lambda: st.text() | st.frozensets(hashables) | st.lists(hashables).map(tuple)) -values = st.deferred(lambda: hashables | objtree) -objtree = st.deferred(lambda: st.text() | st.dictionaries(hashables, values) | st.lists(values) | st.sets(hashables) | st.lists(hashables).map(tuple)) - -# note: use all() so as to not eat all the RAM :p - -class LogAndCompare: - def __init__(self, left, right): - self._itl = left - self._itr = right - self.left = [] - self.right = [] - def __iter__(self): - return self - def __next__(self): - try: - left = next(self._itl) - except abdl.ValidationError as e: - e.tb = traceback.format_exc() - left = e - try: - right = next(self._itr) - except abdl.ValidationError as e: - e.tb = traceback.format_exc() - right = e - self.left.append(left) - self.right.append(right) - return left == right or (type(left), type(right)) == (abdl.ValidationError,)*2 - def __repr__(self): - return "LogAndCompare(left=" + repr(self.left) + ", right=" + repr(self.right) + ")" - - -@hypothesis.given(objtree, st.just(abdl.compile("->X"))) -def test_basic_iterator(foo, pat): - assert all(LogAndCompare(pat.match(foo), map(lambda x: {"X": x}, pairs(foo)))) - -@hypothesis.given(objtree, st.just(abdl.compile("->X->Y"))) -def test_two_depths(foo, pat): - def deep(foo): - for x in pairs(foo): - for y in pairs(x[1]): - yield {"X": x, "Y": y} - assert all(LogAndCompare(pat.match(foo), deep(foo))) - -@hypothesis.given(objtree, st.just(abdl.compile("->X->Y->Z->W"))) -def test_four_depths(foo, pat): - def deep(foo): - for x in pairs(foo): - for y in pairs(x[1]): - for z in pairs(y[1]): - for w in pairs(z[1]): - yield {"X": x, "Y": y, "Z": z, "W": w} - assert all(LogAndCompare(pat.match(foo), deep(foo))) - -@hypothesis.given(st.dictionaries(st.text(), st.text()) | st.sets(st.text()), st.just(abdl.compile("->/.../"))) -def test_regex(foo, pat): - # no bindings on this one :< - def deep(foo): - for x in pairs(foo): - if re.search("...", x[0]): - yield {} - else: - raise abdl.ValidationError - assert all(LogAndCompare(pat.match(foo), deep(foo))) - -@hypothesis.given(objtree, st.just(abdl.compile("->/.../?"))) -def test_regex_skippable_vs_objtree(foo, pat): - assert all(LogAndCompare(pat.match(foo), ({} for x in pairs(foo) if isinstance(x[0], str) and re.search("...", x[0])))) - -@hypothesis.given(st.dictionaries(st.text(), st.text()) | st.sets(st.text()), st.just(abdl.compile("->/.../->Y"))) -def test_regex_and_bind(foo, pat): - def deep(foo): - for x in pairs(foo): - if re.search("...", x[0]): - for y in pairs(x[1]): - yield {"Y": y} - else: - raise abdl.ValidationError - assert all(LogAndCompare(pat.match(foo), deep(foo))) - -@hypothesis.given(objtree, st.just(abdl.compile("->/.../?->Y"))) -def test_regex_skippable_and_bind_vs_objtree(foo, pat): - def deep(foo): - for x in pairs(foo): - if isinstance(x[0], str) and re.search("...", x[0]): - for y in pairs(x[1]): - yield {"Y": y} - assert all(LogAndCompare(pat.match(foo), deep(foo))) - -@hypothesis.given(objtree, st.just(abdl.compile("->/^...$/?->Y"))) -def test_regex_anchored_skippable_and_bind_vs_objtree(foo, pat): - def deep(foo): - for x in pairs(foo): - if isinstance(x[0], str) and re.search("^...$", x[0]): - for y in pairs(x[1]): - yield {"Y": y} - assert all(LogAndCompare(pat.match(foo), deep(foo))) - -@hypothesis.given(objtree, st.just(abdl.compile("->''?->Y"))) -def test_empty_literal_vs_objtree(foo, pat): - def deep(foo): - for x in pairs(foo): - if x[0] == '': - for y in pairs(x[1]): - yield {"Y": y} - assert all(LogAndCompare(pat.match(foo), deep(foo))) - -defs = {'a': (dict, list, set)} -@hypothesis.given(objtree, st.just(abdl.compile("->X:?$a->Y", defs=defs))) -def test_type(foo, pat): - def deep(foo): - for x in pairs(foo): - if isinstance(x[1], (dict, list, set)): - for y in pairs(x[1]): - yield {"X": x, "Y": y} - assert all(LogAndCompare(pat.match(foo), deep(foo))) - -defs = {'a': (dict, list, set), 'b': (dict, set), 'c': dict} -@hypothesis.given(objtree, st.just(abdl.compile("->X:?$a:?$b:?$c->Y", defs=defs))) -def test_multi_type(foo, pat): - def deep(foo): - for x in pairs(foo): - if isinstance(x[1], dict): - for y in pairs(x[1]): - yield {"X": x, "Y": y} - assert all(LogAndCompare(pat.match(foo), deep(foo))) - -defs = {'a': (dict, list, set), 'b': (dict, set), 'c': dict} -@hypothesis.given(objtree, st.just(abdl.compile("->X:$a:$b:$c->Y", defs=defs))) -@hypothesis.settings(suppress_health_check=[hypothesis.HealthCheck.too_slow]) -def test_multi_type_with_validation_errors(foo, pat): - def deep(foo): - for x in pairs(foo): - if isinstance(x[1], dict): - for y in pairs(x[1]): - yield {"X": x, "Y": y} - else: - raise abdl.ValidationError - assert all(LogAndCompare(pat.match(foo), deep(foo))) - -@hypothesis.given(st.dictionaries(st.frozensets(st.text()), st.text()), st.just(abdl.compile("->[:?$sets->A]->D", {'sets': collections.abc.Set}))) -def test_subtree_partial(foo, pat): - def deep(foo): - for x in pairs(foo): - if isinstance(x[0], collections.abc.Set): - for a in pairs(x[0]): - for d in pairs(x[1]): - yield {"A": a, "D": d} - assert all(LogAndCompare(pat.match(foo), deep(foo))) - -@hypothesis.given(objtree, st.just(abdl.compile("->X->$a->Z", {'a': '0'}))) -def test_param(foo, pat): - def deep(foo): - for x in pairs(foo): - try: - y = x['0'] - except (TypeError, IndexError, KeyError): - raise abdl.ValidationError - else: - for z in pairs(y): - yield {"X": x, "Z": z} - assert all(LogAndCompare(pat.match(foo), deep(foo))) - -def test_basic_value_subtree(): - matcher = abdl.match("(->foo'foo')(->bar'bar')", {'foo': 1, 'bar': 2}) - assert list(matcher) == [{'foo': ('foo', 1), 'bar': ('bar', 2)}] - -# FIXME -#@hypothesis.given(objtree, st.text()) -#def test_exhaustive(foo, pat): -# hypothesis.assume(not re.match("^%s+$", pat)) -# hypothesis.assume(pat) -# try: -# compiled = abdl.compile(pat) -# print(pat) -# except abdl.PatternError: -# hypothesis.assume(False) -# compiled.match(foo) diff --git a/testing/test_examples.py b/testing/test_examples.py deleted file mode 100644 index 02532cc..0000000 --- a/testing/test_examples.py +++ /dev/null @@ -1,26 +0,0 @@ -import abdl - -def test_basic_example(): - m = next(abdl.match("->X:?$dict->Y", {"foo": 1, "bar": {"baz": 2}}, {'dict': dict})) - assert m['X'][0] == 'bar' - assert m['Y'][0] == 'baz' - assert m['Y'][1] == 2 - -def test_basic_2(): - m = next(abdl.match("->'projects':?$d->P/[0-9a-fA-F]{40}|[0-9a-fA-F]{64}/?:?$d->U:?$d->B", {"projects": {"385e734a52e13949a7a5c71827f6de920dbfea43": {"https://soniex2.autistic.space/git-repos/ganarchy.git": {"HEAD": {"active": True}}}}}, {'d': dict})) - assert m['P'][0] == "385e734a52e13949a7a5c71827f6de920dbfea43" - assert m['U'][0] == "https://soniex2.autistic.space/git-repos/ganarchy.git" - assert m['B'][0] == "HEAD" - assert m['B'][1] == {"active": True} - -def test_spaces(): - pat = abdl.compile("""-> 'projects'? - -> commit /[0-9a-fA-F]{40}|[0-9a-fA-F]{64}/? :?$dict - -> url :?$dict - -> branch :?$dict""", {'dict': dict}) - data = {"projects": {"385e734a52e13949a7a5c71827f6de920dbfea43": {"https://soniex2.autistic.space/git-repos/ganarchy.git": {"HEAD": {"active": True}}}}} - m = next(pat.match(data)) - assert m['commit'][0] == "385e734a52e13949a7a5c71827f6de920dbfea43" - assert m['url'][0] == "https://soniex2.autistic.space/git-repos/ganarchy.git" - assert m['branch'][0] == "HEAD" - assert m['branch'][1] == {"active": True} diff --git a/testing/test_ops_abdl.py b/testing/test_ops_abdl.py deleted file mode 100644 index fe50369..0000000 --- a/testing/test_ops_abdl.py +++ /dev/null @@ -1,161 +0,0 @@ -# Tests abdl.py internals - -import abdl - -import re - -class OpHelper: - def __init__(self, pat, ops=None): - self.pat = pat - if not ops: - self.ops = pat._ops - else: - self.ops = ops - self.pos = -1 - - def done(self): - assert self.pos + 1 == len(self.ops) - - def __enter__(self): - self.pos += 1 - first = self.pos - assert not isinstance(self.ops[first], abdl._End) - while not isinstance(self.ops[self.pos], abdl._End): - self.pos += 1 - assert isinstance(self.ops[self.pos], abdl._End) - return self.ops[first:self.pos] - - def __exit__(self, exc_type, exc_value, traceback): - pass - -def expect_types(seq, *tys): - assert len(seq) == len(tys) - assert(all(map(lambda x: isinstance(*x), zip(seq, tys)))) - -def expect_idents(oph, *idents): - for ident in idents: - with oph as ops: - expect_types(ops, abdl._Arrow, abdl._Ident) - assert ops[1].key == ident - -def test_empty_iterator_pattern(): - oph = OpHelper(abdl.compile("")) - oph.done() - -def test_four_depths_pattern(): - oph = OpHelper(abdl.compile("->X->Y->Z->W")) - expect_idents(oph, "X", "Y", "Z", "W") - oph.done() - -def test_regex_pattern(): - oph = OpHelper(abdl.compile("->/.../")) - with oph as ops: - expect_types(ops, abdl._Arrow, abdl._RegexKey) - assert ops[1].key == '...' - assert ops[1].compiled == re.compile('...') - assert ops[1].skippable == False - oph.done() - -def test_regex_skippable_pattern(): - oph = OpHelper(abdl.compile("->/.../?")) - with oph as ops: - expect_types(ops, abdl._Arrow, abdl._RegexKey) - assert ops[1].key == '...' - assert ops[1].compiled == re.compile('...') - assert ops[1].skippable == True - oph.done() - -def test_regex_and_bind_pattern(): - oph = OpHelper(abdl.compile("->/.../->Y")) - with oph as ops: - expect_types(ops, abdl._Arrow, abdl._RegexKey) - assert ops[1].key == '...' - assert ops[1].compiled == re.compile('...') - assert ops[1].skippable == False - expect_idents(oph, "Y") - oph.done() - -def test_empty_literal_skippable_and_bind_pattern(): - oph = OpHelper(abdl.compile("->''?->Y")) - with oph as ops: - expect_types(ops, abdl._Arrow, abdl._StringKey) - assert ops[1].key == '' - assert ops[1].skippable == True - expect_idents(oph, "Y") - oph.done() - -def test_type_pattern(): - oph = OpHelper(abdl.compile("->X:?$a->Y", defs={'a': (dict, list, set)})) - assert oph.pat._defs['a'] == (dict, list, set) - with oph as ops: - expect_types(ops, abdl._Arrow, abdl._Ident, abdl._Ty) - assert ops[1].key == 'X' - assert ops[2].key == 'a' - assert ops[2].skippable == True - expect_idents(oph, "Y") - oph.done() - -def test_multi_type_pattern(): - oph = OpHelper(abdl.compile("->X:$a:?$b:?$c->Y", defs={'a': (dict, list, set), 'b': (dict, set), 'c': dict})) - assert oph.pat._defs['a'] == (dict, list, set) - assert oph.pat._defs['b'] == (dict, set) - assert oph.pat._defs['c'] == dict - with oph as ops: - expect_types(ops, abdl._Arrow, abdl._Ident, abdl._Ty, abdl._Ty, abdl._Ty) - assert ops[1].key == 'X' - assert ops[2].key == 'a' - assert ops[2].skippable == False - assert ops[3].key == 'b' - assert ops[3].skippable == True - assert ops[4].key == 'c' - assert ops[4].skippable == True - expect_idents(oph, "Y") - oph.done() - -def test_key_subtree_pattern(): - oph = OpHelper(abdl.compile("->[:?$set->A]->D", defs={'set': set})) - assert oph.pat._defs['set'] == set - with oph as ops: - expect_types(ops, abdl._Arrow, abdl._KeySubtree) - oph2 = OpHelper(None, ops=ops[1].key) - with oph2 as ops2: - expect_types(ops2, abdl._Ty, abdl._Arrow, abdl._Ident) - assert ops2[0].key == 'set' - assert ops2[0].skippable == True - assert ops2[2].key == 'A' - oph2.done() - expect_idents(oph, "D") - oph.done() - -def test_param_pattern(): - oph = OpHelper(abdl.compile("->X->$a->Z", defs={'a': '0'})) - assert oph.pat._defs['a'] == '0' - expect_idents(oph, "X") - with oph as ops: - expect_types(ops, abdl._Arrow, abdl._Param) - assert ops[1].key == 'a' - assert ops[1].skippable == False - expect_idents(oph, "Z") - oph.done() - -def test_value_subtree_pattern(): - oph = OpHelper(abdl.compile("(->foo'foo')(->bar'bar')")) - with oph as ops: - expect_types(ops, abdl._ValueSubtree) - oph2 = OpHelper(None, ops=ops[0].key) - with oph2 as ops2: - expect_types(ops2, abdl._Arrow, abdl._Ident, abdl._StringKey) - assert ops2[1].key == 'foo' - assert ops2[2].key == 'foo' - assert ops2[2].skippable == False - oph2.done() - with oph as ops: - expect_types(ops, abdl._ValueSubtree) - oph2 = OpHelper(None, ops=ops[0].key) - with oph2 as ops2: - expect_types(ops2, abdl._Arrow, abdl._Ident, abdl._StringKey) - assert ops2[1].key == 'bar' - assert ops2[2].key == 'bar' - assert ops2[2].skippable == False - oph2.done() - oph.done() -- cgit 1.4.1