def _add_arbitrary_filter_node(name, index: SDIndex, schema): int_index = False if 'unique_values' in index.__dir__(): indexed_values = index.unique_values() if indexed_values and isinstance(indexed_values[0], int): int_index = True node = Integer(name=name) if int_index else SingleLine(name=name) node = node.bind(**schema.bindings) schema.add(node)
class RateSchema(colander.MappingSchema): """Rate sheet data structure.""" subject = ReferenceSchema(reftype=RateSubjectReference) object = ReferenceSchema(reftype=RateObjectReference) rate = Integer() def validator(self, node, value): """ Validate the rate. 1. Validate that the subject is the user who is currently logged-in. 2. Ensure that no other rate for the same subject/object combination exists, except predecessors of this version. 3. Ask the validator registered for *object* whether *rate* is valid. In this way, `IRateable` subclasses can modify the range of allowed ratings by registering their own `IRateValidator` adapter. """ # TODO make this validator deferred # TODO add post_pool validator request = node.bindings['request'] self._validate_subject_is_current_user(node, value, request) self._ensure_rate_is_unique(node, value, request) self._query_registered_object_validator(node, value, request) def _validate_subject_is_current_user(self, node, value, request): user = get_user(request) if user is None or user != value['subject']: err = colander.Invalid(node) err['subject'] = 'Must be the currently logged-in user' raise err def _ensure_rate_is_unique(self, node, value, request): # Other rates with the same subject and object may occur below the # current context (earlier versions of the same rate item). # If they occur elsewhere, an error is thrown. adhocracy_catalog = find_catalog(request.context, 'adhocracy') index = adhocracy_catalog['reference'] reference_subject = Reference(None, IRate, 'subject', value['subject']) query = index.eq(reference_subject) reference_object = Reference(None, IRate, 'object', value['object']) query &= index.eq(reference_object) system_catalog = find_catalog(request.context, 'system') path_index = system_catalog['path'] query &= path_index.noteq(resource_path(request.context), depth=None) elements = query.execute(resolver=None) if elements: err = colander.Invalid(node) err['object'] = 'Another rate by the same user already exists' raise err def _query_registered_object_validator(self, node, value, request): registry = request.registry rate_validator = registry.getAdapter(value['object'], IRateValidator) if not rate_validator.validate(value['rate']): err = colander.Invalid(node) err['rate'] = rate_validator.helpful_error_message() raise err
class AssetMetadataSchema(MappingSchema): """Data structure storing asset metadata.""" mime_type = SingleLine(readonly=True) size = Integer(readonly=True) filename = SingleLine(readonly=True) attached_to = UniqueReferences(readonly=True, backref=True, reftype=AssetReference)
class CommentableSchema(MappingSchema): """Commentable sheet data structure. `post_pool`: Pool to post new :class:`adhocracy_sample.resource.IComment`. """ comments_count = Integer(readonly=True, default=deferred_default_comment_count) post_pool = PostPool(iresource_or_service_name='comments')
def _add_additional_nodes(self, schema: MappingSchema, params: dict): if params.get('serialization_form', False) == 'content': elements = schema['elements'] typ_copy = deepcopy(elements.children[0].typ) typ_copy.serialization_form = 'content' elements.children[0].typ = typ_copy if params.get('show_count', True): # pragma: no branch child = Integer(default=0, missing=drop, name='count') schema.add(child) if params.get('show_frequency', False): child = SchemaNode(MappingType(unknown='preserve'), default={}, missing=drop, name='aggregateby') schema.add(child) return schema
class RateSchema(MappingSchema): """Rate sheet data structure.""" subject = ReferenceSchema(reftype=RateSubjectReference) object = ReferenceSchema(reftype=RateObjectReference) rate = Integer() preparer = deferred_anonymize_rate_subject @deferred def validator(self, kw: dict) -> callable: """Validate the rate.""" # TODO add post_pool validator context = kw['context'] request = kw['request'] registry = kw['registry'] return All( create_validate_rate_value(registry), create_validate_subject(request), create_validate_is_unique(context, request), )
def make_one(self): from adhocracy_core.schema import Integer return Integer()
def create_arbitrary_filter_node(index, example_value, query): return Integer()
class GETPoolRequestSchema(MappingSchema): """GET parameters accepted for pool queries.""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Raise if unknown to tell client the query parameters are wrong. self.typ.unknown = 'raise' # TODO For now we don't have a way to specify GET parameters that can # be repeated, e.g. 'sheet=Blah&sheet=Blub'. The querystring is converted # by Cornice into a MultiDict (http://docs.pylonsproject.org/projects # /pyramid/en/master/api/interfaces.html#pyramid.interfaces.IMultiDict), # which by default will only return the LAST value if a key is specified # several times. One possible workaround is to allow specifying multiple # values as a comma-separated list instead of repeated key=value pairs, # e.g. 'sheet=Blah,Blub'. This would require a custom Multiple SchemaNode # that wraps a SchemaType, e.g. # sheet = Multiple(Interface(), missing=None, sep=',') # Elements in this schema were multiple values should be allowed: # sheet, aggregateby, tag. depth = PoolQueryDepth() elements = PoolElementsForm(missing=drop) count = Boolean(missing=drop) sort = SingleLine(missing=drop, validator=deferred_validate_sort) reverse = Boolean(missing=drop) # TODO: validate limit, offset to be multiple of 10, 20, 50, 100, 200, 500 limit = Integer(missing=drop) offset = Integer(missing=drop) aggregateby = SingleLine(missing=drop, validator=deferred_validate_aggregateby) def deserialize(self, cstruct=null): # noqa """Deserialize the :term:`cstruct` into an :term:`appstruct`. Adapt key/values to :class:`adhocracy_core.interfaces.SearchQuery`. for BBB. TODO: Change API according to internal SearchQuery api. refactor to follow coding guideline better. """ depth_cstruct = cstruct.get('depth', None) if depth_cstruct == 'all': cstruct['depth'] = 100 appstruct = super().deserialize(cstruct) search_query = {} if appstruct: # pragma: no branch search_query['root'] = self.bindings['context'] if 'depth' in appstruct: # pragma: no branch depth = appstruct['depth'] if depth == 100: depth = None search_query['depth'] = depth if 'elements' in appstruct: elements = appstruct.get('elements') search_query['serialization_form'] = elements if elements == 'omit': search_query['resolve'] = False interfaces = () if 'sheet' in appstruct: interfaces = appstruct['sheet'] if interfaces: search_query['interfaces'] = interfaces if 'aggregateby' in appstruct: search_query['frequency_of'] = appstruct['aggregateby'] search_query['show_frequency'] = True if 'sort' in appstruct: search_query['sort_by'] = appstruct['sort'] if 'limit' in appstruct: search_query['limit'] = appstruct['limit'] if 'offset' in appstruct: search_query['offset'] = appstruct['offset'] if 'reverse' in appstruct: search_query['reverse'] = appstruct['reverse'] if 'count' in appstruct: search_query['show_count'] = appstruct['count'] fields = tuple([x.name for x in GETPoolRequestSchema().children]) fields += ('sheet', ) for filter, query in appstruct.items(): if filter in fields + SearchQuery._fields: continue if ':' in filter: if 'references' not in search_query: # pragma: no branch search_query['references'] = [] isheet_name, isheet_field = filter.split(':') isheet = resolver.resolve(isheet_name) target = appstruct[filter] reference = ReferenceTuple(None, isheet, isheet_field, target) search_query['references'].append(reference) else: if 'indexes' not in search_query: search_query['indexes'] = {} if filter == 'content_type': search_query['indexes']['interfaces'] = appstruct[ 'content_type'] continue search_query['indexes'][filter] = query return search_query
class FieldComparableInteger(FieldComparableBase): """Tuple with values FieldComparable and Integer.""" value = Integer()
class KeywordComparableInteger(KeywordComparableBase): """Tuple with values KeywordComparable and Integer.""" value = Integer()
class WinnerInfoSchema(MappingSchema): funding = Integer()
class DurationSchema(MappingSchema): duration = Integer(missing=required)
class ServiceKontoSchema(MappingSchema): """Data structure for ServiceKonto user information.""" userid = Integer()