Mercurial > code > home > repos > homeauto
comparison 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 |
comparison
equal
deleted
inserted
replaced
1667:a2347393b43e | 1668:89e53cb8a01c |
---|---|
17 ChunkPrimaryTriple = Tuple[Optional[Node], Node, Optional[Node]] | 17 ChunkPrimaryTriple = Tuple[Optional[Node], Node, Optional[Node]] |
18 | 18 |
19 | 19 |
20 @dataclass | 20 @dataclass |
21 class AlignedRuleChunk: | 21 class AlignedRuleChunk: |
22 """a possible association between a rule chunk and a workingSet chunk. Use | 22 """a possible association between a rule chunk and a workingSet chunk. You can test |
23 matches() to see if the rule actually fits (and then we might cache some of | 23 whether the association would still be possible under various additional bindings.""" |
24 that work when computing the new bindings""" | |
25 ruleChunk: 'Chunk' | 24 ruleChunk: 'Chunk' |
26 workingSetChunk: 'Chunk' | 25 workingSetChunk: 'Chunk' |
27 | 26 |
28 def totalBindingIfThisStmtWereTrue(self, prevBindings: CandidateBinding) -> CandidateBinding: | 27 def __post_init__(self): |
29 outBinding = prevBindings.copy() | 28 if not self.matches(): |
29 raise Inconsistent() | |
30 | |
31 def newBindingIfMatched(self, prevBindings: CandidateBinding) -> CandidateBinding: | |
32 """supposing this rule did match the statement, what new bindings would | |
33 that produce? | |
34 | |
35 raises Inconsistent if the existing bindings mean that our aligned | |
36 chunks can no longer match. | |
37 """ | |
38 outBinding = CandidateBinding({}) | |
30 for rt, ct in zip(self.ruleChunk._allTerms(), self.workingSetChunk._allTerms()): | 39 for rt, ct in zip(self.ruleChunk._allTerms(), self.workingSetChunk._allTerms()): |
31 if isinstance(rt, (Variable, BNode)): | 40 if isinstance(rt, (Variable, BNode)): |
41 if prevBindings.contains(rt) and prevBindings.applyTerm(rt) != ct: | |
42 msg = f'{rt=} {ct=} {prevBindings=}' if log.isEnabledFor(logging.DEBUG) else '' | |
43 raise Inconsistent(msg) | |
32 if outBinding.contains(rt) and outBinding.applyTerm(rt) != ct: | 44 if outBinding.contains(rt) and outBinding.applyTerm(rt) != ct: |
33 msg = f'{rt=} {ct=} {outBinding=}' if log.isEnabledFor(logging.DEBUG) else '' | 45 # maybe this can happen, for stmts like ?x :a ?x . |
34 raise Inconsistent(msg) | 46 raise Inconsistent("outBinding inconsistent with itself") |
35 outBinding.addNewBindings(CandidateBinding({rt: ct})) | 47 outBinding.addNewBindings(CandidateBinding({rt: ct})) |
48 else: | |
49 if rt != ct: | |
50 # getting here means prevBindings was set to something our | |
51 # rule statement disagrees with. | |
52 raise Inconsistent(f'{rt=} != {ct=}') | |
36 return outBinding | 53 return outBinding |
37 | 54 |
38 # could combine this and totalBindingIf into a single ChunkMatch object | |
39 def matches(self) -> bool: | 55 def matches(self) -> bool: |
40 """could this rule, with its BindableTerm wildcards, match workingSetChunk?""" | 56 """could this rule, with its BindableTerm wildcards, match workingSetChunk?""" |
41 for selfTerm, otherTerm in zip(self.ruleChunk._allTerms(), self.workingSetChunk._allTerms()): | 57 for selfTerm, otherTerm in zip(self.ruleChunk._allTerms(), self.workingSetChunk._allTerms()): |
42 if not isinstance(selfTerm, (Variable, BNode)) and selfTerm != otherTerm: | 58 if not isinstance(selfTerm, (Variable, BNode)) and selfTerm != otherTerm: |
43 return False | 59 return False |
93 # log.debug(f'{INDENT*6} computing {self}.ruleMatchesFrom({workingSet}') | 109 # log.debug(f'{INDENT*6} computing {self}.ruleMatchesFrom({workingSet}') |
94 allChunksIter = workingSet.allChunks() | 110 allChunksIter = workingSet.allChunks() |
95 if "stable failures please": | 111 if "stable failures please": |
96 allChunksIter = sorted(allChunksIter) | 112 allChunksIter = sorted(allChunksIter) |
97 for chunk in allChunksIter: | 113 for chunk in allChunksIter: |
98 aligned = AlignedRuleChunk(self, chunk) | 114 try: |
99 if aligned.matches(): | 115 aligned = AlignedRuleChunk(self, chunk) |
100 yield aligned | 116 except Inconsistent: |
117 continue | |
118 yield aligned | |
101 | 119 |
102 def __repr__(self): | 120 def __repr__(self): |
103 pre = ('+'.join('%s' % elem for elem in self.subjList) + '+' if self.subjList else '') | 121 pre = ('+'.join('%s' % elem for elem in self.subjList) + '+' if self.subjList else '') |
104 post = ('+' + '+'.join('%s' % elem for elem in self.objList) if self.objList else '') | 122 post = ('+' + '+'.join('%s' % elem for elem in self.objList) if self.objList else '') |
105 return pre + repr(self.primary) + post | 123 return pre + repr(self.primary) + post |
130 | 148 |
131 def applyChunky(cb: CandidateBinding, | 149 def applyChunky(cb: CandidateBinding, |
132 g: Iterable[AlignedRuleChunk], | 150 g: Iterable[AlignedRuleChunk], |
133 returnBoundStatementsOnly=True) -> Iterator[AlignedRuleChunk]: | 151 returnBoundStatementsOnly=True) -> Iterator[AlignedRuleChunk]: |
134 for aligned in g: | 152 for aligned in g: |
153 bound = aligned.ruleChunk.apply(cb, returnBoundStatementsOnly=returnBoundStatementsOnly) | |
135 try: | 154 try: |
136 bound = aligned.ruleChunk.apply(cb, returnBoundStatementsOnly=returnBoundStatementsOnly) | 155 yield AlignedRuleChunk(bound, aligned.workingSetChunk) |
137 except BindingUnknown: | 156 except Inconsistent: |
138 log.debug(f'{INDENT*7} CB.apply cant bind {aligned} using {cb.binding}') | 157 pass |
139 | |
140 continue | |
141 log.debug(f'{INDENT*7} CB.apply took {aligned} to {bound}') | |
142 | |
143 yield AlignedRuleChunk(bound, aligned.workingSetChunk) | |
144 | 158 |
145 | 159 |
146 class ChunkedGraph: | 160 class ChunkedGraph: |
147 """a Graph converts 1-to-1 with a ChunkedGraph, where the Chunks have | 161 """a Graph converts 1-to-1 with a ChunkedGraph, where the Chunks have |
148 combined some statements together. (The only exception is that bnodes for | 162 combined some statements together. (The only exception is that bnodes for |