async def test_create_annotation(db, guillotina_main): db = await get_database('db') login() async with transaction(db=db): container = await create_content_in_container(db, 'Container', 'container', title='Container') ob = await create_content_in_container(container, 'Item', 'foobar') annotations = IAnnotations(ob) data = AnnotationData() data['foo'] = 'bar' await annotations.async_set('foobar', data) async with transaction(db=db): container = await db.async_get('container') ob = await container.async_get('foobar') annotations = IAnnotations(ob) assert 'foobar' in (await annotations.async_keys()) await annotations.async_del('foobar') async with transaction(db=db): container = await db.async_get('container') ob = await container.async_get('foobar') annotations = IAnnotations(ob) assert 'foobar' not in (await annotations.async_keys()) await container.async_del('foobar') await db.async_del('container')
async def test_create_annotation(db, guillotina_main): root = get_utility(IApplication, name='root') db = root['db'] request = get_mocked_request(db) login(request) async with managed_transaction(request=request, write=True): container = await create_content_in_container( db, 'Container', 'container', request=request, title='Container') ob = await create_content_in_container( container, 'Item', 'foobar', request=request) annotations = IAnnotations(ob) data = AnnotationData() data['foo'] = 'bar' await annotations.async_set('foobar', data) async with managed_transaction(request=request, write=True): container = await db.async_get('container') ob = await container.async_get('foobar') annotations = IAnnotations(ob) assert 'foobar' in (await annotations.async_keys()) await annotations.async_del('foobar') async with managed_transaction(request=request, write=True): container = await db.async_get('container') ob = await container.async_get('foobar') annotations = IAnnotations(ob) assert 'foobar' not in (await annotations.async_keys()) await container.async_del('foobar') await db.async_del('container')
async def test_create_annotation(db, guillotina_main): db = await get_database("db") login() async with transaction(db=db): container = await create_content_in_container(db, "Container", "container", title="Container") ob = await create_content_in_container(container, "Item", "foobar") annotations = IAnnotations(ob) data = AnnotationData() data["foo"] = "bar" await annotations.async_set("foobar", data) async with transaction(db=db): container = await db.async_get("container") ob = await container.async_get("foobar") annotations = IAnnotations(ob) assert "foobar" in (await annotations.async_keys()) await annotations.async_del("foobar") async with transaction(db=db): container = await db.async_get("container") ob = await container.async_get("foobar") annotations = IAnnotations(ob) assert "foobar" not in (await annotations.async_keys()) await container.async_del("foobar") await db.async_del("container")
async def iter_buckets(self, context): for index in sorted(self.annotations_metadata.keys()): annotation_name = self.get_annotation_name(index) annotations_container = IAnnotations(context) annotation = annotations_container.get(annotation_name, _default) if annotation is _default: annotation = await annotations_container.async_get( annotation_name, _default) if annotation is _default: continue yield annotation
async def get(self, context, create=True): annotations_container = IAnnotations(context) numpy_object = annotations_container.get(self.prefix, _default) if numpy_object is _default: # needs to be loaded numpy_object = await annotations_container.async_get(self.prefix, _default, reader=reader) if numpy_object is _default: return None return numpy_object
def __init__(self, context): self.__dict__['schema'] = [x for x in self.__implemented__][0] self.__dict__['prefix'] = self.__dict__['schema'].__identifier__ + '.' self.__dict__['data'] = {} self.__dict__['context'] = context # see if annotations are preloaded... annotations_container = IAnnotations(self.__dict__['context']) data = annotations_container.get(self.__annotations_data_key__, _default) if data is not _default: self.__dict__['data'] = data
async def iter_buckets(self, context) -> AsyncIterator[AnnotationData]: annotations_container = IAnnotations(context) for index in sorted(self.annotations_metadata.keys()): annotation_name = self.get_annotation_name(index) annotation = annotations_container.get(annotation_name, _default) if annotation is _default: # pragma: no cover annotation = await annotations_container.async_get( annotation_name, _default) if annotation is _default: continue yield annotation
def __init__(self, context): self.__dict__["schema"] = [x for x in self.__implemented__][0] self.__dict__["prefix"] = self.__dict__["schema"].__identifier__ + "." self.__dict__["data"] = {} self.__dict__["context"] = context # see if annotations are preloaded... annotations_container = IAnnotations(self.__dict__["context"]) data = annotations_container.get(self.__annotations_data_key__, _default) if data is not _default: self.__dict__["data"] = data
async def iter_buckets(self, context) -> AsyncIterator[AnnotationData]: try: annotations_container = IAnnotations(context) except TypeError: return for bucket in self.buckets: annotation_name: str = self.get_annotation_name(bucket["id"]) annotation: AnnotationData = annotations_container.get( annotation_name, _default) if annotation is _default: annotation = await annotations_container.async_get( annotation_name, _default) if annotation is _default: continue yield annotation
async def clear(self, context: IBaseObject): annotations_container = IAnnotations(context) for index in sorted(self.annotations_metadata.keys()): annotation_name = self.get_annotation_name(index) await annotations_container.async_del(annotation_name) self.annotations_metadata = {} self.current_annotation_index = 0
async def set(self, context, value): # create annotations_container = IAnnotations(context) obj = NumPyData() obj.value = value obj.register() await annotations_container.async_set(self.prefix, obj)
async def create_request(self): request = make_request(self.base_request, self.data["req_data"]) g_task_vars.request.set(request) if self.data.get("db_id"): root = get_utility(IApplication, name="root") db = await root.async_get(self.data["db_id"]) g_task_vars.db.set(db) # Add a transaction Manager to request tm = db.get_transaction_manager() g_task_vars.tm.set(tm) # Start a transaction txn = await tm.begin() # Get the root of the tree context = await tm.get_root(txn=txn) if self.data.get("container_id"): container = await context.async_get(self.data["container_id"]) if container is None: raise Exception( f'Could not find container: {self.data["container_id"]}' ) g_task_vars.container.set(container) annotations_container = IAnnotations(container) container_settings = await annotations_container.async_get( REGISTRY_DATA_KEY) layers = container_settings.get(ACTIVE_LAYERS_KEY, []) for layer in layers: try: alsoProvides(request, import_class(layer)) except ModuleNotFoundError: pass g_task_vars.registry.set(container_settings) return request
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 load(self, create=False): annotations_container = IAnnotations(self.__dict__['context']) data = annotations_container.get(self.__annotations_data_key__, _default) if data is not _default: # data is already preloaded, we do not need to get from db again... self.__dict__['data'] = data return annotations = await annotations_container.async_get(self.__annotations_data_key__) if annotations is None: if create: annotations = AnnotationData() await annotations_container.async_set(self.__annotations_data_key__, annotations) else: annotations = {} # fallback, assumed only for reading here... self.__dict__['data'] = annotations
async def load(self, create=False): annotations_container = IAnnotations(self.__dict__["context"]) data = annotations_container.get(self.__annotations_data_key__, _default) if data is not _default: # data is already preloaded, we do not need to get from db again... self.__dict__["data"] = data return annotations = await annotations_container.async_get(self.__annotations_data_key__) if annotations is None: if create: annotations = AnnotationData() await annotations_container.async_set(self.__annotations_data_key__, annotations) else: annotations = {} # fallback, assumed only for reading here... self.__dict__["data"] = annotations
async def clear(self, context): annotations_container = IAnnotations(context) for bucket in self.buckets: annotation_name = self.get_annotation_name(bucket["id"]) await annotations_container.async_del(annotation_name) self.buckets = self._get_empty_buckets()
async def get_registry(self, container, request): if request is None: request = get_current_request() if hasattr(request, 'container_settings'): return request.container_settings annotations_container = IAnnotations(container) request.container_settings = await annotations_container.async_get(REGISTRY_DATA_KEY) return request.container_settings
async def get_annotation(self, context, annotation_index, create=True): annotation_name = self.get_annotation_name(annotation_index) annotations_container = IAnnotations(context) annotation = annotations_container.get(annotation_name, _default) if annotation is _default: annotation = await annotations_container.async_get( annotation_name, _default) if annotation is _default: if not create: return # create annotation = AnnotationData() annotation.update({'items': []}) await annotations_container.async_set(annotation_name, annotation) if annotation_index not in self.annotations_metadata: self.annotations_metadata[annotation_index] = {} return annotation
async def _get_registry_or_create(self): annotations_container = IAnnotations(self.context) object_settings = await annotations_container.async_get("default" ) # noqa if object_settings is None: # need to create annotation... object_settings = AnnotationData() await annotations_container.async_set("default", object_settings) return object_settings
async def use_container(self, container: IResource): self.request.container = container self.request._container_id = container.id annotations_container = IAnnotations(container) self.request.container_settings = await annotations_container.async_get( REGISTRY_DATA_KEY) layers = self.request.container_settings.get(ACTIVE_LAYERS_KEY, []) for layer in layers: alsoProvides(self.request, import_class(layer))
async def get_registry(self, refresh=False): if (refresh and hasattr(self.request, 'container_settings') and REGISTRY_DATA_KEY in self._get_annotations()): txn = get_transaction(self.request) await txn.refresh(self.request.container_settings) if hasattr(self.request, 'container_settings'): return self.request.container_settings annotations_container = IAnnotations(self.container) self.request.container_settings = await annotations_container.async_get(REGISTRY_DATA_KEY) # noqa return self.request.container_settings
async def get_annotation(self, context, annotation_index, create=True): annotation_name = self.get_annotation_name(annotation_index) annotations_container = IAnnotations(context) annotation = annotations_container.get(annotation_name, _default) if annotation is _default: annotation = await annotations_container.async_get( annotation_name, _default) if annotation is _default: if not create: return # create annotation = AnnotationData() annotation.update({ 'items': [] }) await annotations_container.async_set(annotation_name, annotation) if annotation_index not in self.annotations_metadata: self.annotations_metadata[annotation_index] = {} return annotation
async def get_annotation(self, context: IBaseObject, annotation_index: int, create: bool = True) -> Optional[IAnnotationData]: annotation_name = self.get_annotation_name(annotation_index) annotations_container = IAnnotations(context) annotation = annotations_container.get(annotation_name, _default) if annotation is _default: annotation = await annotations_container.async_get( annotation_name, _default) if annotation is _default: if not create: return None # create annotation = AnnotationData() annotation.update({"items": []}) await annotations_container.async_set(annotation_name, annotation) if annotation_index not in self.annotations_metadata: self.annotations_metadata[annotation_index] = {} return annotation
async def traverse(request, parent, path): """Do not use outside the main router function.""" if IApplication.providedBy(parent): request.application = parent if not path: return parent, path assert request is not None # could be used for permissions, etc if not ITraversable.providedBy(parent): # not a traversable context return parent, path try: if path[0][0] == '_' or path[0] in ('.', '..'): raise HTTPUnauthorized() if path[0][0] == '@': # shortcut return parent, path if IAsyncContainer.providedBy(parent): context = await parent.async_get(path[0], suppress_events=True) if context is None: return parent, path else: context = parent[path[0]] except (TypeError, KeyError, AttributeError): return parent, path if IDatabase.providedBy(context): request._db_write_enabled = app_settings['check_writable_request']( request) request._db_id = context.id # Add a transaction Manager to request tm = request._tm = context.get_transaction_manager() # Start a transaction txn = await tm.begin(request=request) # Get the root of the tree context = await tm.get_root(txn=txn) if IContainer.providedBy(context): request._container_id = context.id request.container = context annotations_container = IAnnotations(request.container) request.container_settings = await annotations_container.async_get( REGISTRY_DATA_KEY) layers = request.container_settings.get(ACTIVE_LAYERS_KEY, []) for layer in layers: try: alsoProvides(request, import_class(layer)) except ModuleNotFoundError: logger.error('Can not apply layer ' + layer, request=request) return await traverse(request, context, path[1:])
async def load(self, create=False): annotations_container = IAnnotations(self.__dict__['context']) annotations = {} try: annotations = await annotations_container.async_get( self.__annotations_data_key) except KeyError: if create: annotations = AnnotationData() await annotations_container.async_set( self.__annotations_data_key, annotations) self.__dict__['data'] = annotations
async def get_registry(self, refresh=False): if (refresh and self.object_settings is not None): txn = get_transaction(self.request) await txn.refresh(self.object_settings) annotations_container = IAnnotations(self.context) self.object_settings = await annotations_container.async_get('default') if self.object_settings is None: # need to create annotation... self.object_settings = AnnotationData() await annotations_container.async_set('default', self.object_settings) return self.object_settings
async def get_registry(context=None) -> typing.Optional[IRegistry]: registry = task_vars.registry.get() if registry is None: container = task_vars.container.get() if container is None and context is not None: container = find_container(context) if container is None: return None annotations_container = IAnnotations(container) from guillotina.registry import REGISTRY_DATA_KEY registry = await annotations_container.async_get(REGISTRY_DATA_KEY) task_vars.registry.set(registry) return registry
async def get_annotation(self, context, key=None, anno_id=None, create=True) -> typing.Optional[AnnotationData]: if anno_id is None: bidx, bucket = self._find_bucket(key) annotation_name = self.get_annotation_name(bucket["id"]) else: annotation_name = self.get_annotation_name(anno_id) annotations_container = IAnnotations(context) annotation = annotations_container.get(annotation_name, _default) if annotation is _default: annotation = await annotations_container.async_get( annotation_name, _default) if annotation is _default: if not create: return None annotation = AnnotationData({"keys": [], "values": []}) await annotations_container.async_set(annotation_name, annotation) return annotation
async def clone_request(self, method, endpoint, payload, headers): container_url = IAbsoluteURL(self.request.container, self.request)() url = posixpath.join(container_url, endpoint) parsed = urlparse(url) dct = {'method': method, 'url': URL(url), 'path': parsed.path} dct['headers'] = CIMultiDict(headers) dct['raw_headers'] = tuple( (k.encode('utf-8'), v.encode('utf-8')) for k, v in headers.items()) message = self.request._message._replace(**dct) payload_writer = mock.Mock() payload_writer.write_eof.side_effect = noop payload_writer.drain.side_effect = noop protocol = mock.Mock() protocol.transport = test_utils._create_transport(None) protocol.writer = payload_writer request = self.request.__class__( message, SimplePayload(payload), protocol, payload_writer, self.request._task, self.request._loop, client_max_size=self.request._client_max_size, state=self.request._state.copy(), scheme=self.request.scheme, host=self.request.host, remote=self.request.remote) request._db_write_enabled = True request._db_id = self.request._db_id request._tm = self.request._tm request._txn = self.request._txn request._container_id = self.context.id request.container = self.context annotations_container = IAnnotations(self.context) request.container_settings = await annotations_container.async_get( REGISTRY_DATA_KEY) layers = request.container_settings.get(ACTIVE_LAYERS_KEY, []) for layer in layers: try: alsoProvides(request, import_class(layer)) except ModuleNotFoundError: pass request._futures = self.request._futures return request
async def traverse(request, parent, path): """Do not use outside the main router function.""" if IApplication.providedBy(parent): request.application = parent if not path: return parent, path assert request is not None # could be used for permissions, etc if not ITraversable.providedBy(parent): # not a traversable context return parent, path try: if path[0].startswith('_'): raise HTTPUnauthorized() if IAsyncContainer.providedBy(parent): context = await parent.async_get(path[0]) else: context = parent[path[0]] except (TypeError, KeyError, AttributeError): return parent, path if IDatabase.providedBy(context): request._db_write_enabled = False request._db_id = context.id # Create a transaction Manager request._tm = context.new_transaction_manager() # Start a transaction try: await request._tm.begin(request=request) except asyncpg.exceptions.UndefinedTableError: pass # Get the root of the tree context = await request._tm.root() if ISite.providedBy(context): request._site_id = context.id request.site = context annotations_container = IAnnotations(request.site) request.site_settings = await annotations_container.async_get( REGISTRY_DATA_KEY) layers = request.site_settings.get(ACTIVE_LAYERS_KEY, []) for layer in layers: alsoProvides(request, import_class(layer)) return await traverse(request, context, path[1:])
async def install(self): # Creating and registering a local registry from guillotina.registry import Registry annotations_container = IAnnotations(self) registry = Registry() await annotations_container.async_set(REGISTRY_DATA_KEY, registry) # Set default plugins registry.register_interface(ILayers) registry.register_interface(IAddons) layers = registry.for_interface(ILayers) layers['active_layers'] = frozenset() roles = IPrincipalRoleManager(self) roles.assign_role_to_principal('guillotina.ContainerAdmin', ROOT_USER_ID) roles.assign_role_to_principal('guillotina.Owner', ROOT_USER_ID)
async def test_create_annotation(dummy_txn_root): async with dummy_txn_root as root: ob1 = ObjectTest() await root.async_set('ob1', ob1) annotations = IAnnotations(ob1) with pytest.raises(KeyError): await annotations.async_set('test', 'hola') ob2 = ObjectTest() assert ob2.__of__ is None assert ob2._p_jar is None assert ob2.__name__ is None assert ob2.__parent__ is None assert len(ob1.__annotations__) == 0 await annotations.async_set('test2', ob2) assert ob2.__of__ is ob1._p_oid assert ob2._p_jar is ob1._p_jar assert ob2.__name__ == 'test2' assert ob2.__parent__ is None assert len(ob1.__annotations__) == 1