Mercurial > code > home > repos > homeauto
diff service/mqtt_to_rdf/stmt_chunk.py @ 1668:89e53cb8a01c
fix some harder tests. Mostly, _advanceTheStack needed to spin the odometer rings starting from the other side, to get all the right combos
author | drewp@bigasterisk.com |
---|---|
date | Tue, 21 Sep 2021 22:29:19 -0700 |
parents | 1a7c1261302c |
children | 9d00adef0b22 |
line wrap: on
line diff
--- a/service/mqtt_to_rdf/stmt_chunk.py Tue Sep 21 22:19:11 2021 -0700 +++ b/service/mqtt_to_rdf/stmt_chunk.py Tue Sep 21 22:29:19 2021 -0700 @@ -19,23 +19,39 @@ @dataclass class AlignedRuleChunk: - """a possible association between a rule chunk and a workingSet chunk. Use - matches() to see if the rule actually fits (and then we might cache some of - that work when computing the new bindings""" + """a possible association between a rule chunk and a workingSet chunk. You can test + whether the association would still be possible under various additional bindings.""" ruleChunk: 'Chunk' workingSetChunk: 'Chunk' - def totalBindingIfThisStmtWereTrue(self, prevBindings: CandidateBinding) -> CandidateBinding: - outBinding = prevBindings.copy() + def __post_init__(self): + if not self.matches(): + raise Inconsistent() + + def newBindingIfMatched(self, prevBindings: CandidateBinding) -> CandidateBinding: + """supposing this rule did match the statement, what new bindings would + that produce? + + raises Inconsistent if the existing bindings mean that our aligned + chunks can no longer match. + """ + outBinding = CandidateBinding({}) for rt, ct in zip(self.ruleChunk._allTerms(), self.workingSetChunk._allTerms()): if isinstance(rt, (Variable, BNode)): + if prevBindings.contains(rt) and prevBindings.applyTerm(rt) != ct: + msg = f'{rt=} {ct=} {prevBindings=}' if log.isEnabledFor(logging.DEBUG) else '' + raise Inconsistent(msg) if outBinding.contains(rt) and outBinding.applyTerm(rt) != ct: - msg = f'{rt=} {ct=} {outBinding=}' if log.isEnabledFor(logging.DEBUG) else '' - raise Inconsistent(msg) + # maybe this can happen, for stmts like ?x :a ?x . + raise Inconsistent("outBinding inconsistent with itself") outBinding.addNewBindings(CandidateBinding({rt: ct})) + else: + if rt != ct: + # getting here means prevBindings was set to something our + # rule statement disagrees with. + raise Inconsistent(f'{rt=} != {ct=}') return outBinding - # could combine this and totalBindingIf into a single ChunkMatch object def matches(self) -> bool: """could this rule, with its BindableTerm wildcards, match workingSetChunk?""" for selfTerm, otherTerm in zip(self.ruleChunk._allTerms(), self.workingSetChunk._allTerms()): @@ -95,9 +111,11 @@ if "stable failures please": allChunksIter = sorted(allChunksIter) for chunk in allChunksIter: - aligned = AlignedRuleChunk(self, chunk) - if aligned.matches(): - yield aligned + try: + aligned = AlignedRuleChunk(self, chunk) + except Inconsistent: + continue + yield aligned def __repr__(self): pre = ('+'.join('%s' % elem for elem in self.subjList) + '+' if self.subjList else '') @@ -132,15 +150,11 @@ g: Iterable[AlignedRuleChunk], returnBoundStatementsOnly=True) -> Iterator[AlignedRuleChunk]: for aligned in g: + bound = aligned.ruleChunk.apply(cb, returnBoundStatementsOnly=returnBoundStatementsOnly) try: - bound = aligned.ruleChunk.apply(cb, returnBoundStatementsOnly=returnBoundStatementsOnly) - except BindingUnknown: - log.debug(f'{INDENT*7} CB.apply cant bind {aligned} using {cb.binding}') - - continue - log.debug(f'{INDENT*7} CB.apply took {aligned} to {bound}') - - yield AlignedRuleChunk(bound, aligned.workingSetChunk) + yield AlignedRuleChunk(bound, aligned.workingSetChunk) + except Inconsistent: + pass class ChunkedGraph: