async def default_get(context, request): """We show the available schemas.""" result = {} factory = get_cached_factory(context.type_name) result["static"] = [] for schema in factory.behaviors or (): result["static"].append(schema.__identifier__) # convert to list, could be frozenset result["dynamic"] = [b for b in context.__behaviors__] result["available"] = [] factory = get_cached_factory(context.type_name) for name, utility in get_utilities_for(IBehavior): serialize = False if name not in result["dynamic"] and name not in result["static"]: adaptable = query_adapter(context, utility.interface, name="", default=None) if adaptable: result["available"].append(name) serialize = True schema_serializer = get_multi_adapter( (utility.interface, request), ISchemaSerializeToJson) result[name] = await schema_serializer() else: serialize = True if serialize: schema_serializer = get_multi_adapter((utility.interface, request), ISchemaSerializeToJson) result[name] = await schema_serializer() return result
async def default_get(context, request): """We show the available schemas.""" result = {} factory = get_cached_factory(context.type_name) result['static'] = [] for schema in factory.behaviors or (): result['static'].append(schema.__identifier__) # convert to list, could be frozenset result['dynamic'] = [b for b in context.__behaviors__] result['available'] = [] factory = get_cached_factory(context.type_name) for name, utility in get_utilities_for(IBehavior): serialize = False if name not in result['dynamic'] and name not in result['static']: adaptable = query_adapter( context, utility.interface, name='', default=None) if adaptable: result['available'].append(name) serialize = True schema_serializer = get_multi_adapter( (utility.interface, request), ISchemaSerializeToJson) result[name] = await schema_serializer() else: serialize = True if serialize: schema_serializer = get_multi_adapter( (utility.interface, request), ISchemaSerializeToJson) result[name] = await schema_serializer() return result
async def __call__(self): parent = self.context.__parent__ if parent is not None: # We render the summary of the parent try: parent_summary = await getMultiAdapter( (parent, self.request), IResourceSerializeToJsonSummary)() except ComponentLookupError: parent_summary = {} else: parent_summary = {} result = { '@id': IAbsoluteURL(self.context, self.request)(), '@type': self.context.type_name, 'parent': parent_summary, 'creation_date': json_compatible(self.context.creation_date), 'modification_date': json_compatible(self.context.modification_date), 'UID': self.context.uuid, } factory = get_cached_factory(self.context.type_name) main_schema = factory.schema await self.get_schema(main_schema, self.context, result, False) for behavior_schema, behavior in await get_all_behaviors(self.context): await self.get_schema(behavior_schema, behavior, result, True) return result
async def __call__(self, data, validate_all=False, ignore_errors=False): errors = [] factory = get_cached_factory(self.context.type_name) main_schema = factory.schema await self.set_schema( main_schema, self.context, data, errors, validate_all, False) for behavior_schema, behavior in await get_all_behaviors(self.context, load=False): dotted_name = behavior_schema.__identifier__ if dotted_name not in data: # syntax {"namespace.IBehavior": {"foo": "bar"}} # we're not even patching this behavior if no iface found in payload continue if IAsyncBehavior.implementedBy(behavior.__class__): # providedBy not working here? await behavior.load(create=True) await self.set_schema( behavior_schema, behavior, data, errors, validate_all, True) if errors and not ignore_errors: raise DeserializationError(errors) self.context._p_register() return self.context
async def get_field(self, field_name): context = self.context if '.' in field_name: schema_klass, field_name = field_name.rsplit('.', 1) if schema_klass not in self.context.__behaviors__: self.ws.send_str( json.dumps({ 't': 'e', 'v': 'Not a valid field on a behavior' })) return schema = resolve_dotted_name(schema_klass) if schema is None: self.ws.send_str( json.dumps({ 't': 'e', 'v': 'Could not find specified schema' })) return behavior = schema(context) context = behavior else: factory = get_cached_factory(self.context.type_name) schema = factory.schema try: field = schema[field_name] except KeyError: self.ws.send_str( json.dumps({ 't': 'e', 'v': 'Not a valid field on a behavior' })) return return context, field
async def set_constraint(context, request): # validate input data = await request.json() if not isinstance(data, list): raise ErrorResponse( "MissingList", str("value type"), status=412, reason=error_reasons.DESERIALIZATION_FAILED, ) tn = getattr(context, "type_name", None) factory = get_cached_factory(tn) allowed_types = factory.allowed_types for element in data: if allowed_types is not None and element not in allowed_types: raise ErrorResponse( "WrongType", str("wrong type"), status=412, reason=error_reasons.DESERIALIZATION_FAILED, ) setattr(context, "__allowed_types__", data) context.register()
async def __call__(self): ''' PUT means we're completely replacing the content so we need to delete data from existing behaviors and content schemas. Then do the regular patch serialization ''' annotations_container = IAnnotations(self.context) for schema, behavior in await get_all_behaviors(self.context, load=False): if hasattr(behavior, '__annotations_data_key__'): await annotations_container.async_del( behavior.__annotations_data_key__) try: behavior.data.clear() for local_prop in behavior.__local__properties__: if local_prop in self.context.__dict__: del self.context.__dict__[local_prop] except AttributeError: pass self.context.__behaviors__ = frozenset({}) factory = get_cached_factory(self.context.type_name) if factory.schema is not None: for name in factory.schema.names(): if name in self.context.__dict__: del self.context.__dict__[name] return await super().__call__()
async def get_field(self, field_name): context = self.context if "." in field_name: schema_klass, field_name = field_name.rsplit(".", 1) if schema_klass not in self.context.__behaviors__: self.ws.send_bytes( json.dumps({ "t": "e", "v": "Not a valid field on a behavior" })) return schema = resolve_dotted_name(schema_klass) if schema is None: self.ws.send_bytes( json.dumps({ "t": "e", "v": "Could not find specified schema" })) return behavior = schema(context) context = behavior else: factory = get_cached_factory(self.context.type_name) schema = factory.schema try: field = schema[field_name] except KeyError: self.ws.send_bytes( json.dumps({ "t": "e", "v": "Not a valid field on a behavior" })) return return context, field
async def get_constraints(context, request): at = getattr(context, '__allowed_types__', None) if at is None: tn = getattr(context, 'type_name', None) factory = get_cached_factory(tn) at = factory.allowed_types if factory.allowed_types is not None else [] return at
async def append_constraint(context, request): data = await request.json() if not isinstance(data, dict): raise ErrorResponse( "MissingLDict", str("value type"), status=412, reason=error_reasons.DESERIALIZATION_FAILED, ) operation = data["op"] patch_data = data["types"] if operation == "add": tn = getattr(context, "type_name", None) factory = get_cached_factory(tn) allowed_types = factory.allowed_types for element in patch_data: if allowed_types is not None and element not in allowed_types: raise ErrorResponse( "WrongType", str("wrong type"), status=412, reason=error_reasons.DESERIALIZATION_FAILED, ) at = getattr(context, "__allowed_types__", None) if at is None and allowed_types is not None: at = allowed_types.copy() elif at is None: at = [] for element in patch_data: if element not in at: at.append(element) setattr(context, "__allowed_types__", at) elif operation == "del": at = getattr(context, "__allowed_types__", None) if at is None: factory = get_cached_factory(tn) if factory.allowed_types is None: at = [] else: at = factory.allowed_types.copy() for element in patch_data: if element in at: at.remove(element) setattr(context, "__allowed_types__", at) context.register()
async def __call__(self, include=[], omit=[]): self.include = include self.omit = omit parent = self.context.__parent__ if parent is not None: # We render the summary of the parent try: parent_summary = await get_multi_adapter( (parent, self.request), IResourceSerializeToJsonSummary)() except ComponentLookupError: parent_summary = {} else: parent_summary = {} factory = get_cached_factory(self.context.type_name) behaviors = [] for behavior_schema in factory.behaviors or (): behaviors.append(behavior_schema.__identifier__) result = { '@id': IAbsoluteURL(self.context, self.request)(), '@type': self.context.type_name, '@name': self.context.__name__, '@uid': self.context.uuid, '@static_behaviors': behaviors, 'parent': parent_summary, # should be @parent 'is_folderish': IFolder.providedBy(self.context), # eek, should be @folderish? 'creation_date': json_compatible(self.context.creation_date), 'modification_date': json_compatible(self.context.modification_date), 'UID': self.context.uuid, # should be removed } main_schema = factory.schema await self.get_schema(main_schema, self.context, result, False) # include can be one of: # - <field name> on content schema # - namespace.IBehavior # - namespace.IBehavior.field_name included_ifaces = [name for name in self.include if '.' in name] included_ifaces.extend([name.rsplit('.', 1)[0] for name in self.include if '.' in name]) for behavior_schema, behavior in await get_all_behaviors(self.context, load=False): if '*' not in self.include: dotted_name = behavior_schema.__identifier__ if (dotted_name in self.omit or (len(included_ifaces) > 0 and dotted_name not in included_ifaces)): # make sure the schema isn't filtered continue if (not getattr(behavior, 'auto_serialize', True) and dotted_name not in included_ifaces): continue if IAsyncBehavior.implementedBy(behavior.__class__): # providedBy not working here? await behavior.load(create=False) await self.get_schema(behavior_schema, behavior, result, True) return result
async def __call__(self, include=[], omit=[]): self.include = include self.omit = omit parent = self.context.__parent__ if parent is not None: # We render the summary of the parent try: parent_summary = await get_multi_adapter( (parent, self.request), IResourceSerializeToJsonSummary)() except ComponentLookupError: parent_summary = {} else: parent_summary = {} result = { '@id': IAbsoluteURL(self.context, self.request)(), '@type': self.context.type_name, '@name': self.context.__name__, '@uid': self.context.uuid, 'parent': parent_summary, 'is_folderish': IFolder.providedBy(self.context), 'creation_date': json_compatible(self.context.creation_date), 'modification_date': json_compatible(self.context.modification_date), 'UID': self.context.uuid, } factory = get_cached_factory(self.context.type_name) main_schema = factory.schema await self.get_schema(main_schema, self.context, result, False) # include can be one of: # - <field name> on content schema # - namespace.IBehavior # - namespace.IBehavior.field_name included_ifaces = [name for name in self.include if '.' in name] included_ifaces.extend( [name.rsplit('.', 1)[0] for name in self.include if '.' in name]) for behavior_schema, behavior in await get_all_behaviors(self.context, load=False): dotted_name = behavior_schema.__identifier__ if (dotted_name in self.omit or (len(included_ifaces) > 0 and dotted_name not in included_ifaces)): # make sure the schema isn't filtered continue if (not getattr(behavior, 'auto_serialize', True) and dotted_name not in included_ifaces): continue if IAsyncBehavior.implementedBy(behavior.__class__): # providedBy not working here? await behavior.load(create=False) await self.get_schema(behavior_schema, behavior, result, True) return result
async def append_constraint(context, request): data = await request.json() if not isinstance(data, dict): raise ErrorResponse('MissingLDict', str('value type'), status=412, reason=error_reasons.DESERIALIZATION_FAILED) operation = data['op'] patch_data = data['types'] if operation == 'add': tn = getattr(context, 'type_name', None) factory = get_cached_factory(tn) allowed_types = factory.allowed_types for element in patch_data: if allowed_types is not None and element not in allowed_types: raise ErrorResponse( 'WrongType', str('wrong type'), status=412, reason=error_reasons.DESERIALIZATION_FAILED) at = getattr(context, '__allowed_types__', None) if at is None and allowed_types is not None: at = allowed_types.copy() elif at is None: at = [] for element in patch_data: if element not in at: at.append(element) setattr(context, '__allowed_types__', at) elif operation == 'del': at = getattr(context, '__allowed_types__', None) if at is None: factory = get_cached_factory(tn) if factory.allowed_types is None: at = [] else: at = factory.allowed_types.copy() for element in patch_data: if element in at: at.remove(element) setattr(context, '__allowed_types__', at) context.register()
async def get_field_value(context, request): field_name = request.matchdict["dotted_name"] if "." in field_name: # behavior field lookup iface_dotted = ".".join(field_name.split(".")[:-1]) field_name = field_name.split(".")[-1] try: schema = resolve_dotted_name(iface_dotted) except ModuleNotFoundError: return HTTPNotFound( content={"reason": f"Could resolve: {iface_dotted}"}) try: field = schema[field_name] except KeyError: return HTTPNotFound(content={"reason": f"No field: {field_name}"}) try: behavior = await get_behavior(context, schema) except AttributeError: return HTTPNotFound( content={"reason": f"Could not load behavior: {iface_dotted}"}) if behavior is None: return HTTPNotFound( content={"reason": f"Not valid behavior: {iface_dotted}"}) field = field.bind(behavior) field_context = behavior else: # main object field factory = get_cached_factory(context.type_name) schema = factory.schema try: field = schema[field_name] except KeyError: return HTTPNotFound(content={"reason": f"No field: {field_name}"}) field = field.bind(context) field_context = context # check permission read_permissions = merged_tagged_value_dict(schema, read_permission.key) serializer = get_multi_adapter((context, request), IResourceSerializeToJson) if not serializer.check_permission(read_permissions.get(field_name)): return HTTPUnauthorized( content={"reason": "You are not authorized to render this field"}) field_renderer = query_multi_adapter((context, request, field), IFieldValueRenderer) if field_renderer is None: return await serializer.serialize_field(field_context, field) else: return await field_renderer()
async def default_delete(context, request): data = await request.json() behavior = data.get('behavior', None) factory = get_cached_factory(context.type_name) behavior_class = resolve_dotted_name(behavior) if behavior_class is not None: if behavior_class in factory.behaviors: return Response(response={}, status=201) if behavior not in context.__behaviors__: return Response(response={}, status=201) context.remove_behavior(behavior) return {}
async def delete_behavior(context, behavior): factory = get_cached_factory(context.type_name) behavior_class = resolve_dotted_name(behavior) if behavior_class is not None: if behavior_class in factory.behaviors: return Response(content={ 'reason': 'Behaviors defined on this type must be present and cannot be dynamically removed' }, status=412) if behavior not in context.__behaviors__: return Response(content={'reason': 'Not in behaviors'}, status=412) context.remove_behavior(behavior) return {}
async def delete_behavior(context, behavior): factory = get_cached_factory(context.type_name) behavior_class = resolve_dotted_name(behavior) if behavior_class is not None: if behavior_class in factory.behaviors: return Response(content={ 'reason': 'Behaviors defined on this type must be present and cannot be dynamically removed' }, status=412) if behavior not in context.__behaviors__: return Response(content={ 'reason': 'Not in behaviors' }, status=412) context.remove_behavior(behavior) return {}
async def delete_behavior(context, behavior): factory = get_cached_factory(context.type_name) behavior_class = resolve_dotted_name(behavior) if behavior_class is not None: if behavior_class in factory.behaviors: return Response(content={ 'reason': 'Not not remove this type of behavior' }, status=412) if behavior not in context.__behaviors__: return Response(content={ 'reason': 'Not in behaviors' }, status=412) context.remove_behavior(behavior) return {}
async def default_patch(context, request): data = await request.json() behavior = data.get('behavior', None) try: behavior_class = resolve_dotted_name(behavior) except ModuleNotFoundError: behavior_class = None if behavior_class is None: return Response(response={}, status=404) factory = get_cached_factory(context.type_name) if behavior_class in factory.behaviors: return Response(response={}, status=201) if behavior in context.__behaviors__: return Response(response={}, status=201) context.add_behavior(behavior) return {}
async def default_patch(context, request): data = await request.json() behavior = data.get("behavior", None) try: behavior_class = resolve_dotted_name(behavior) except ModuleNotFoundError: behavior_class = None if behavior_class is None: return Response(content={"reason": "Could not find behavior"}, status=404) factory = get_cached_factory(context.type_name) if behavior_class in factory.behaviors: return Response(content={"reason": "Already in behaviors"}, status=412) if behavior in context.__behaviors__: return Response(content={"reason": "Already in behaviors"}, status=412) context.add_behavior(behavior) return {}
async def __call__( self, data: Dict[str, Any], validate_all: bool = False, ignore_errors: bool = False, create: bool = False, ) -> IResource: errors: List[Dict[str, Any]] = [] # do behavior first in case they modify context values for behavior_schema, behavior in await get_all_behaviors(self.context, load=False): dotted_name = behavior_schema.__identifier__ if dotted_name not in data: # syntax {"namespace.IBehavior": {"foo": "bar"}} # we're not even patching this behavior if no iface found in payload if create: # signal to caching engine to cache no data here so # we prevent a future lookup try: txn = self.context.__txn__ await txn._cache.set( _EMPTY, container=self.context, id=behavior.__annotations_data_key__, variant="annotation", ) except AttributeError: pass continue if IAsyncBehavior.implementedBy(behavior.__class__): # providedBy not working here? await behavior.load(create=True) await self.set_schema(behavior_schema, behavior, data, errors, validate_all, True) factory = get_cached_factory(self.context.type_name) main_schema = factory.schema await self.set_schema(main_schema, self.context, data, errors, validate_all, False) if errors and not ignore_errors: raise DeserializationError(errors) return self.context
async def __call__(self, data, validate_all=False, ignore_errors=False): errors = [] factory = get_cached_factory(self.context.type_name) main_schema = factory.schema await self.set_schema(main_schema, self.context, data, errors, validate_all, False) for behavior_schema, behavior in await get_all_behaviors( self.context, True): await self.set_schema(behavior_schema, behavior, data, errors, validate_all, True) if errors and not ignore_errors: raise DeserializationError(errors) self.context._p_register() return self.context
async def __call__(self): parent = self.context.__parent__ if parent is not None: # We render the summary of the parent try: parent_summary = await getMultiAdapter( (parent, self.request), IResourceSerializeToJsonSummary)() except ComponentLookupError: parent_summary = {} else: parent_summary = {} result = { '@id': IAbsoluteURL(self.context, self.request)(), '@type': self.context.portal_type, 'parent': parent_summary, 'created': json_compatible(self.context.created), 'modified': json_compatible(self.context.modified), 'UID': self.context.uuid, } factory = get_cached_factory(self.context.portal_type) main_schema = factory.schema await self.get_schema(main_schema, self.context, result, False) for behavior_schema in factory.behaviors or (): behavior = behavior_schema(self.context) if IAsyncBehavior.implementedBy(behavior.__class__): # providedBy not working here? await behavior.load() await self.get_schema(behavior_schema, behavior, result, True) for dynamic_behavior in self.context.__behaviors__ or (): dynamic_behavior_obj = BEHAVIOR_CACHE[dynamic_behavior] behavior = dynamic_behavior_obj(self.context) if IAsyncBehavior.implementedBy(dynamic_behavior_obj.__class__): # providedBy not working here? await behavior.load() await self.get_schema(dynamic_behavior_obj, behavior, result, True) return result
async def default_patch(context, request): data = await request.json() behavior = data.get('behavior', None) try: behavior_class = resolve_dotted_name(behavior) except ModuleNotFoundError: behavior_class = None if behavior_class is None: return Response(content={ 'reason': 'Could not find behavior' }, status=404) factory = get_cached_factory(context.type_name) if behavior_class in factory.behaviors: return Response(content={ 'reason': 'Already in behaviors' }, status=412) if behavior in context.__behaviors__: return Response(content={ 'reason': 'Already in behaviors' }, status=412) context.add_behavior(behavior) return {}
async def __call__(self, data, validate_all=False, ignore_errors=False, create=False): errors = [] # do behavior first in case they modify context values for behavior_schema, behavior in await get_all_behaviors(self.context, load=False): dotted_name = behavior_schema.__identifier__ if dotted_name not in data: # syntax {"namespace.IBehavior": {"foo": "bar"}} # we're not even patching this behavior if no iface found in payload if create: # signal to caching engine to cache no data here so # we prevent a future lookup try: txn = self.context._p_jar await txn._cache.set( _EMPTY, container=self.context, id=behavior.__annotations_data_key__, variant='annotation') except AttributeError: pass continue if IAsyncBehavior.implementedBy(behavior.__class__): # providedBy not working here? await behavior.load(create=True) await self.set_schema( behavior_schema, behavior, data, errors, validate_all, True) factory = get_cached_factory(self.context.type_name) main_schema = factory.schema await self.set_schema( main_schema, self.context, data, errors, validate_all, False) if errors and not ignore_errors: raise DeserializationError(errors) self.context._p_register() return self.context
async def __call__(self, data, validate_all=False): modified = False errors = [] factory = get_cached_factory(self.context.portal_type) main_schema = factory.schema await self.set_schema(main_schema, self.context, data, errors, validate_all, False) for behavior_schema in factory.behaviors or (): if behavior_schema.__identifier__ in data: behavior = behavior_schema(self.context) if IAsyncBehavior.implementedBy(behavior.__class__): # providedBy not working here? await behavior.load(create=True) await self.set_schema(behavior_schema, behavior, data, errors, validate_all, True) for dynamic_behavior in self.context.__behaviors__ or (): dynamic_behavior_obj = BEHAVIOR_CACHE[dynamic_behavior] if dynamic_behavior_obj.__identifier__ in data: behavior = dynamic_behavior_obj(self.context) if IAsyncBehavior.implementedBy( dynamic_behavior_obj.__class__): # providedBy not working here? await behavior.load(create=True) await self.set_schema(dynamic_behavior_obj, behavior, data, errors, validate_all, True) if errors: raise DeserializationError(errors) if modified: self.context._p_register() await notify(ObjectModifiedEvent(self.context, data)) return self.context
async def default_get(context, request): """We show the available schemas.""" result = {} factory = get_cached_factory(context.type_name) result['static'] = [] for schema in factory.behaviors or (): result['static'].append(schema.__identifier__) # convert to list, could be frozenset result['dynamic'] = [b for b in context.__behaviors__] result['available'] = [] for iface, utility in getUtilitiesFor(IBehavior): serialize = False if isinstance(iface, str): name = iface else: name = iface.__identifier__ if name not in result['dynamic'] and name not in result['static']: adaptable = queryAdapter(context, utility.interface, name='', default=None) if adaptable: result['available'].append(name) serialize = True schema_serializer = getMultiAdapter( (utility.interface, request), ISchemaSerializeToJson) result[name] = await schema_serializer() else: serialize = True if serialize: schema_serializer = getMultiAdapter((utility.interface, request), ISchemaSerializeToJson) result[name] = await schema_serializer() return result
def get_allowed_types(self) -> list: pt = getattr(self.context, 'portal_type', None) if pt: factory = get_cached_factory(pt) return factory.allowed_types return None
async def __call__(self, include=None, omit=None): self.include = include or [] self.omit = omit or [] parent = self.context.__parent__ if parent is not None: # We render the summary of the parent try: parent_summary = await get_multi_adapter( (parent, self.request), IResourceSerializeToJsonSummary)() except ComponentLookupError: parent_summary = {} else: parent_summary = {} factory = get_cached_factory(self.context.type_name) behaviors = [] for behavior_schema in factory.behaviors or (): behaviors.append(behavior_schema.__identifier__) result = { "@id": get_object_url(self.context, self.request), "@type": self.context.type_name, "@name": self.context.__name__, "@uid": self.context.uuid, "@static_behaviors": behaviors, "parent": parent_summary, # should be @parent "is_folderish": IFolder.providedBy(self.context), # eek, should be @folderish? "creation_date": json_compatible(self.context.creation_date), "modification_date": json_compatible(self.context.modification_date), } main_schema = factory.schema await self.get_schema(main_schema, self.context, result, False) # include can be one of: # - <field name> on content schema # - namespace.IBehavior # - namespace.IBehavior.field_name included_ifaces = [name for name in self.include if "." in name] included_ifaces.extend( [name.rsplit(".", 1)[0] for name in self.include if "." in name]) for behavior_schema, behavior in await get_all_behaviors(self.context, load=False): if "*" not in self.include: dotted_name = behavior_schema.__identifier__ if dotted_name in self.omit or (len(included_ifaces) > 0 and dotted_name not in included_ifaces): # make sure the schema isn't filtered continue if not getattr(behavior, "auto_serialize", True) and dotted_name not in included_ifaces: continue if IAsyncBehavior.implementedBy(behavior.__class__): # providedBy not working here? await behavior.load(create=False) await self.get_schema(behavior_schema, behavior, result, True) for post_serialize_processors in app_settings["post_serialize"]: await apply_coroutine(post_serialize_processors, self.context, result) return result
def is_globally_allowed(self, type_id: str) -> bool: factory = get_cached_factory(type_id) return factory.globally_addable
def get_allowed_types(self) -> list: tn = getattr(self.context, 'type_name', None) if tn: factory = get_cached_factory(tn) return factory.allowed_types return None
def get_allowed_types(self) -> list: tn = getattr(self.context, 'type_name', None) if tn: factory = get_cached_factory(tn) return factory.allowed_types return []
def get_allowed_types(self) -> Optional[list]: tn = getattr(self.context, "type_name", None) if tn: factory = get_cached_factory(tn) return factory.allowed_types return []
def create_content_factory(proto_name, proto_definition): parent_interface = import_class( proto_definition.get('inherited_interface', 'guillotina.interfaces.content.IFolder')) parent_class = import_class( proto_definition.get('inherited_class', 'guillotina.content.Folder')) schema_fields, tags = get_fields( properties=proto_definition.get('properties')) for fieldset_id, fieldset_list in proto_definition.get('fieldsets', {}).items(): for field_id in fieldset_list: tags.setdefault(field_id, {})['fieldset'] = fieldset_id class_interface = InterfaceClass('I' + proto_name, (parent_interface, ), schema_fields, __module__='guillotina_cms.interfaces') for field_id, tag in tags.items(): for tag_id, tag_metadata in tag.items(): if tag_id in SUPPORTED_DIRECTIVES: if tag_metadata is None: SUPPORTED_DIRECTIVES[tag_id].apply(class_interface, field_id) elif isinstance(tag_metadata, dict): SUPPORTED_DIRECTIVES[tag_id].apply(class_interface, field_id, **tag_metadata) elif isinstance(tag_metadata, list): SUPPORTED_DIRECTIVES[tag_id].apply(class_interface, field_id, *tag_metadata) elif tag_id == 'fieldset': SUPPORTED_DIRECTIVES[tag_id].apply(class_interface, field_id, tag_metadata) elif isinstance(tag_metadata, str): SUPPORTED_DIRECTIVES[tag_id].apply( class_interface, **{field_id: tag_metadata}) klass = type(proto_name, (parent_class, ), {}) klass.__module__ = 'guillotina_cms.dyncontent' setattr(dyncontent, proto_name, klass) behaviors = [] for bhr in proto_definition.get('behaviors', []): if bhr in BEHAVIOR_CACHE: behaviors.append(BEHAVIOR_CACHE[bhr]) else: raise Exception(f"Behavior not found {bhr}") contenttype = { 'schema': class_interface, 'type_name': proto_name, 'allowed_types': proto_definition.get('allowed_types', []), 'add_permission': proto_definition.get('add_permission', 'guillotina.AddContent'), 'behaviors': behaviors } utility = query_utility(IResourceFactory, name=proto_name) if utility is not None: sm = get_global_components() sm.unregisterUtility(utility, IResourceFactory, proto_name) configure.register_configuration(klass, contenttype, 'contenttype') root = get_utility(IApplication, name='root') configure.load_configuration(root.app.config, 'guillotina_cms.dyncontent', 'contenttype') root.app.config.execute_actions() configure.clear() load_cached_schema() # Verify its created if proto_name in FACTORY_CACHE: del FACTORY_CACHE[proto_name] get_cached_factory(proto_name)