def capture_token(self, token): '''Captures an emitted token. When a token is emitted if the last previously created part is a term that *is* the same as the :attr:`IGeneratorToken.expression`, then this last term should be removed from the particles collection. This is because in a query like:: these((parent, child) for parent in this for child in parent.children) The `parent.children` emits itself as a query part and immediately it is transformed to a token. :param token: The emitted token :type token: :class:`IGeneratorToken` ''' tokens = self._tokens with context(UNPROXIFING_CONTEXT): assert IGeneratorToken.providedBy(token) parts = self._parts if parts: top = parts.pop(-1) if token.expression is not top: parts.append(top) if token not in tokens: tokens.append(token) self._particles.append(token)
def __init__(self, **kwargs): with context(UNPROXIFING_CONTEXT): self._expression = expression = kwargs.get('expression') assert IExpressionCapable.providedBy(expression) self._token = None self.token = token = kwargs.get('token') assert IGeneratorToken.providedBy(token)
def cmp_terms(t1, t2, strict=False): '''Compares two terms in a partial order. This is a *partial* compare operator. A term `t1 < t2` if and only if `t1` is in the parent-chain of `t2`. If `strict` is False the comparison between expressions will be made with the `eq` operation; otherwise `is` will be used. If either `t1` or `t2` are generator tokens it's :attr:`~xotl.ql.interfaces.IGeneratorToken.expression` is used instead. Examples:: >>> from xotl.ql.core import this, these >>> t1 = this('a').b.c >>> t2 = this('b').b.c.d >>> t3 = this('a').b >>> cmp_terms(t1, t3) 1 # But if equivalence is False neither t1 < t3 nor t3 < t1 holds. >>> cmp_terms(t1, t3, True) 0 # Since t1 and t2 have no comon ancestor, they are not ordered. >>> cmp_terms(t1, t2) 0 >>> query = these((child, brother) ... for parent in this ... for child in parent.children ... for brother in parent.children ... if child is not brother) >>> t1, t2, t3 = query.tokens >>> cmp_terms(t1, t2) -1 >>> cmp_terms(t2, t3) 0 ''' import operator if not strict: test = operator.eq else: test = operator.is_ with context(UNPROXIFING_CONTEXT): if IGeneratorToken.providedBy(t1): t1 = t1.expression if IGeneratorToken.providedBy(t2): t2 = t2.expression if test(t1, t2): return 0 else: t = t1 while t and not test(t, t2): t = t.parent if t: return 1 t = t2 while t and not test(t, t1): t = t.parent if t: return -1 else: return 0