''

def features(self, query):

    logging.debug(('Rendering    %s' % str(query.bbox)))
    tiles = list_tiles(query, self.zoom_adjust)
    features = []
    seen = set()
    for (wkb, props) in load_features(8, self.host, self.port, self.path, tiles):
        if (not self.clipped):
            key = (wkb, tuple(sorted(props.items())))
            if (key in seen):
                continue
            seen.add(key)
        features.append((wkb, utf8_keys(props)))
    if self.sort:
        logging.debug(('Sorting    by    %s    %s' % (self.sort, ('descending' if self.reverse else 'ascending'))))
        key_func = (lambda wkb_props: wkb_props[1].get(self.sort, None))
        features.sort(reverse=self.reverse, key=key_func)
    if (len(features) == 0):
        return PythonDatasource.wkb_features(keys=[], features=[])
    props = zip(*features)[1]
    keys = [set(prop.keys()) for prop in props]
    keys = reduce((lambda a, b: (a & b)), keys)
    return PythonDatasource.wkb_features(keys=keys, features=features)
