def _reduce(func, predicates: List['Predicate']) -> 'Predicate': predicates = flatten_sequence(p for p in predicates if p is not None) if not predicates: return None if len(predicates) == 1: return list(predicates)[0] else: return reduce(func, predicates)
def where(self, *predicates: Tuple['Predicate'], indexed=False) -> 'Batch': """ Return a new batch, containing the resources whose attributes match the given predicates, like `User.created_at >= cutoff_date`, for instance. The new batch is *not* indexed by default, so make sure to set `indexed=True` if you intend to filter the filtered batch further. """ predicate = Predicate.reduce_and(flatten_sequence(predicates)) resources = self._apply_indexes(predicate) return type(self)(resources, indexed=indexed)
def on_decorate(self, handler: 'Action'): event_type = handler.decorator.kwargs['event'] if event_type in KEY_EVENT_TYPES: # look for action `key` attribute and add to "key" event handlers. # otherwise add to "any key" event handlers. key_obj = handler.decorator.kwargs.get('key') if key_obj is not None: for key in set(flatten_sequence(key_obj)): self.key_event_handlers[event_type][key].append(handler) else: self.any_key_event_handlers[event_type].append(handler) return
def where(self, *predicates, **equality_checks): predicates = flatten_sequence(predicates) for field_name, value in equality_checks.items(): resolver_prop = getattr(self.target, field_name) pred = (resolver_prop == value) predicates.append(pred) if predicates: if self.parameters.where: self.parameters.where &= Predicate.reduce_and(predicates) else: self.parameters.where = Predicate.reduce_and(predicates) return self
def including(self, *others) -> Predicate: others = flatten_sequence(others) visited = set() deduplicated = [] for obj in others: if is_resource(obj): if obj._id not in visited: visited.add(obj._id) deduplicated.append(obj._id) else: if obj not in visited: visited.add(obj) deduplicated.append(obj) return ConditionalPredicate(OP_CODE.INCLUDING, self, deduplicated)
def order_by(self, *order_by): order_by = flatten_sequence(order_by) if order_by: self.parameters.order_by = [] for obj in order_by: if isinstance(obj, OrderBy): self.parameters.order_by.append(obj) elif isinstance(obj, str): if obj.lower().endswith(' desc'): order_by_obj = OrderBy(obj.split()[0], desc=True) else: order_by_obj = OrderBy(obj.split()[0], desc=False) if order_by_obj.key not in self.target.ravel.resolvers: raise ValueError( f'uncognized resolver: {order_by_obj.key}') self.parameters.order_by.append(order_by_obj) else: self.parameters.order_by = None return self
def deselect(self, *args): """ Remove the given arguments from the query's requests dict. """ args = flatten_sequence(args) keys = set() for obj in args: if isinstance(obj, str): # if obj is str, replace it with the corresponding resolver # property from the target Resource class. _obj = getattr(self.target, obj, None) if _obj is None: raise ValueError(f'unknown resolver: {obj}') obj = _obj elif is_resource(obj): keys.update(obj.internal.state.keys()) continue elif is_resource_type(obj): keys.update(obj.ravel.resolvers.keys()) continue # build a resolver request request = None if isinstance(obj, LoaderProperty) and (obj.decorator is None): resolver_property = obj keys.add(resolver_property.resolver.name) elif isinstance(obj, ResolverProperty): resolver_property = obj keys.add(resolver_property.resolver.name) elif isinstance(obj, Request): request = obj keys.add(request.resolver.name) for key in keys: if key in self.requests: del self.requests[key] return self
def select(self, *args): args = flatten_sequence(args) for obj in args: if isinstance(obj, str): # if obj is str, replace it with the corresponding resolver # property from the target Resource class. _obj = getattr(self.target, obj, None) if _obj is None: raise ValueError(f'unknown resolver: {obj}') obj = _obj elif is_resource(obj): self.select(obj.internal.state.keys()) continue elif is_resource_type(obj): self.select(obj.ravel.resolvers.keys()) continue # build a resolver request request = None if isinstance(obj, LoaderProperty) and (obj.decorator is None): resolver_property = obj request = Request(resolver_property.resolver) elif isinstance(obj, ResolverProperty): resolver_property = obj request = Request(resolver_property.resolver) elif isinstance(obj, Request): request = obj # finally set the request if one was generated if request: resolver_name = request.resolver.name if resolver_name not in self.target.ravel.virtual_fields: if self.from_request is not None: request.parent = self.from_request self.requests[request.resolver.name] = request return self
def select(self, *args) -> 'Request': from ravel.resolver.resolvers.loader import LoaderProperty from ravel.resolver.resolver_property import ResolverProperty args = flatten_sequence(args) for obj in args: if isinstance(obj, str): # if obj is str, replace it with the corresponding resolver # property from the target Resource class. _obj = getattr(self.resolver.owner, obj, None) if _obj is None: raise ValueError(f'unknown resolver: {obj}') obj = _obj elif is_resource(obj): self.select(obj.internal.state.keys()) continue elif is_resource_type(obj): self.select(obj.ravel.resolvers.keys()) continue # build a resolver request request = None if isinstance(obj, LoaderProperty) and (obj.decorator is None): resolver_property = obj request = Request(resolver_property.resolver) elif isinstance(obj, ResolverProperty): resolver_property = obj request = Request(resolver_property.resolver) elif isinstance(obj, Request): request = obj if request is not None: self.parameters.select.append(request) elif obj is not None: self.parameters.select.append(obj) return self
def excluding(self, *others) -> Predicate: others = flatten_sequence(others) others = {obj._id if is_resource(obj) else obj for obj in others} return ConditionalPredicate(OP_CODE.EXCLUDING, self, others)