xotl.ql.core – The core API

The module xotl.ql.core provide the high level API for obtaining a query object from a query expression.

xotl.ql.core.this

This is an object whose meaning is the entire universe of objects when used as a generator inside a query expression. Its precise semantics varies with the object model. The documentation of query translators must give the precise meaning of this object.

xotl.ql.core.get_query_object(generator, query_type='xotl.ql.core.QueryObject', frame_type=None, **kwargs)

Get the query object from a query expression.

This function expects a query expression in the form of a generator object and returns an object that complies with the interface xotl.ql.interfaces.QueryObject.

Parameters:

This function works by inspecting the byte-code of the generator object to obtain the Query Syntax Tree. This function uses the attribute gi_frame of the generator to build the frame object needed by query objects.

Nested sub-queries are not expanded automatically:

>>> from xotl.ql.core import this, get_query_object
>>> query = get_query_object(y for y in (x for x in this))

>>> print(query.qst)
<ast: Expression>
   body: <ast: GeneratorExp>
      elt: <ast: Name>
         id: 'y'
         ctx: <ast: Load>
      generators[0]: <ast: comprehension>
         target: <ast: Name>
            id: 'y'
            ctx: <ast: Store>
         iter: <ast: Name>
            id: '.0'
            ctx: <ast: Load>

The sub-query (x for x in this) is simply encoded as a variable ‘.0’.

If no frame_type is provided, use the attribute frame_type of the query object type.

Additional keyword arguments are passed unchanged when instantiating the query object.

xotl.ql.core.normalize_query(which, **kwargs)

Ensure a query object.

If which is a query expression (more precisely a generator object) it is passed to get_query_object() along with all keyword arguments.

If which is not a query expression it must be a query object, other types are a TypeError.

class xotl.ql.core.QueryObject(qst, frame, **kwargs)

A query object implementation.

Instances of this class implement the interface xotl.ql.interfaces.QueryObject and this class itself complies with xotl.ql.interfaces.QueryObjectType.

class xotl.ql.core.Frame(locals, globals)

Instances of this class implement the interface xotl.ql.interfaces.Frame and the class itself complies with xotl.ql.interface.FrameType.

The f_locals and f_globals are immutable mapping views that support all the collections.Mapping interface.

In order to support for the view concept to work we keep a references to the original locals and globals.

Additional attributes and methods:

auto_expand_subqueries

When trying to get the name ‘.0’ from either view, if the current value is a generator object obtained via a generator expression, we actually return the result of calling get_query_object() on the current value.

You may suppress this behavior by setting this attribute to False. The default is True.

Warning

Notice this will use the default query object type and frame type.

Example:

>>> from xotl.ql.core import this, get_query_object
>>> query = get_query_object(y for y in (x for x in this))

>>> query.locals['.0']  
<xotl.ql.core.QueryObject...>
xotl.ql.core.thesefy(target, make_subquery=True)

Allow an object to participate in queries.

Example as a wrapper:

class People(object):
    # ...
    pass

query = (who for who in thesefy(People))

Example as a decorator:

@thesefy
class People(object):
    pass

query = (who for who in People)

If target already support the iterable protocol (i.e implement __iter__), return it unchanged.

If make_subquery is True, then the query shown above will be equivalent to:

query = (who for who in (x for x in this if isinstance(x, People)))

If make_subquery is False, thesefy injects an __iter__() that simply returns the same object and a next() method that immediately stops the iteration.

Notice that in order to use make_subquery you call thesefy() as a decorator-returning function:

class Person(object):
    pass

query = (x for x in thesefy(make_subquery=False)(Person))

# or simply as a decorator

@thesefy(make_subquery=False)
class Person(object):
    pass