async def test_write_large_blob_data(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): container = await db.async_get('container') if container is None: container = await create_content_in_container( db, 'Container', 'container', request=request, title='Container') blob = Blob(container) container.blob = blob multiplier = 999999 blobfi = blob.open('w') await blobfi.async_write(b'foobar' * multiplier) async with managed_transaction(request=request): container = await db.async_get('container') assert await container.blob.open().async_read() == (b'foobar' * multiplier) assert container.blob.size == len(b'foobar' * multiplier) assert container.blob.chunks == 6 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_large_upload_chunks(container_requester): async with container_requester as requester: response, status = await requester('POST', '/db/guillotina/', data=json.dumps({ '@type': 'Item', '@behaviors': [IAttachment.__identifier__], 'id': 'foobar' })) assert status == 201 response, status = await requester( 'PATCH', '/db/guillotina/foobar/@upload/file', data=b'X' * 1024 * 1024 * 10, headers={'x-upload-size': str(1024 * 1024 * 10)}) assert status == 200 response, status = await requester( 'GET', '/db/guillotina/foobar/@download/file') assert status == 200 assert len(response) == (1024 * 1024 * 10) request = utils.get_mocked_request(requester.db) root = await utils.get_root(request) async with managed_transaction(request=request, abort_when_done=True): container = await root.async_get('guillotina') obj = await container.async_get('foobar') behavior = IAttachment(obj) await behavior.load() assert behavior.file._blob.chunks == 2
def transaction(self, request=None): if request is None: request = get_mocked_request(self.db) login(request) return wrap_request( request, managed_transaction( request=request, write=True, adopt_parent_txn=True))
async def test_create_contenttype_with_date(container_requester): async with container_requester as requester: response, status = await requester( 'POST', '/db/guillotina/', data=json.dumps({ "@type": "Item", "title": "Item1", "id": "item1", }) ) assert status == 201 date_to_test = "2016-11-30T14:39:07.394273+01:00" response, status = await requester( 'PATCH', '/db/guillotina/item1', data=json.dumps({ "guillotina.behaviors.dublincore.IDublinCore": { "creation_date": date_to_test, "expiration_date": date_to_test } }) ) request = utils.get_mocked_request(requester.db) root = await utils.get_root(request) async with managed_transaction(request=request, abort_when_done=True): container = await root.async_get('guillotina') obj = await container.async_get('item1') from guillotina.behaviors.dublincore import IDublinCore behavior = IDublinCore(obj) await behavior.load() assert behavior.creation_date.isoformat() == date_to_test assert behavior.expiration_date.isoformat() == date_to_test
async def test_tus_multi(container_requester): async with container_requester as requester: response, status = await requester( 'POST', '/db/guillotina/', data=json.dumps({ '@type': 'Item', '@behaviors': [IMultiAttachment.__identifier__], 'id': 'foobar' })) assert status == 201 response, status = await requester( 'OPTIONS', '/db/guillotina/foobar/@tusupload/files/file', headers={ 'Origin': 'http://foobar.com', 'Access-Control-Request-Method': 'POST' }) assert status == 200 response, status = await requester( 'POST', '/db/guillotina/foobar/@tusupload/files/file', headers={ 'UPLOAD-LENGTH': str(1024 * 1024 * 10), 'TUS-RESUMABLE': '1.0.0' }) assert status == 201 response, status = await requester( 'HEAD', '/db/guillotina/foobar/@tusupload/files/file') assert status == 200 for idx in range(10): # 10, 1mb chunks response, status = await requester( 'PATCH', '/db/guillotina/foobar/@tusupload/files/file', headers={ 'CONTENT-LENGTH': str(1024 * 1024 * 1), 'TUS-RESUMABLE': '1.0.0', 'upload-offset': str(1024 * 1024 * idx) }, data=b'X' * 1024 * 1024 * 1) assert status == 200 response, status = await requester( 'GET', '/db/guillotina/foobar/@download/files/file') assert status == 200 assert len(response) == (1024 * 1024 * 10) request = utils.get_mocked_request(requester.db) root = await utils.get_root(request) async with managed_transaction(request=request, abort_when_done=True): container = await root.async_get('guillotina') obj = await container.async_get('foobar') behavior = IMultiAttachment(obj) await behavior.load() assert behavior.files['file']._blob.chunks == 10
async def test_copy_file_ob(container_requester): async with container_requester as requester: response, status = await requester( 'POST', '/db/guillotina/', data=json.dumps({ '@type': 'Item', '@behaviors': ['guillotina.behaviors.attachment.IAttachment'], 'id': 'foobar' })) assert status == 201 response, status = await requester( 'PATCH', '/db/guillotina/foobar/@upload/file', data=b'X' * 1024 * 1024 * 4, headers={'x-upload-size': str(1024 * 1024 * 4)}) assert status == 200 request = utils.get_mocked_request(requester.db) root = await utils.get_root(request) async with managed_transaction(request=request, abort_when_done=True): container = await root.async_get('guillotina') obj = await container.async_get('foobar') attachment = IAttachment(obj) await attachment.load() existing_bid = attachment.file._blob.bid await attachment.file.copy_cloud_file(obj) assert existing_bid != attachment.file._blob.bid
async def get_container(requester=None, request=None): if request is None: request = get_mocked_request(requester.db) root = await get_root(request) async with managed_transaction(request=request): container = await root.async_get('guillotina') return container
async def refresh_index(requester): search = get_utility(ICatalogUtility) request = get_mocked_request(requester.db) container = await get_container(request=request) async with managed_transaction(request=request, adopt_parent_txn=True, abort_when_done=True): await search.refresh(container)
async def setup_next_index(self): self.response.write(b'Creating new index') async with managed_transaction(self.request, write=True, adopt_parent_txn=True): await self.utility.disable_next_index(self.context, request=self.request) async with managed_transaction(self.request, write=True, adopt_parent_txn=True): self.next_index_version, self.work_index_name = await self.create_next_index( ) await self.utility.install_mappings_on_index(self.work_index_name) await self.utility.activate_next_index(self.container, self.next_index_version, request=self.request, force=self.force)
async def test_multi_upload(container_requester): async with container_requester as requester: response, status = await requester( 'POST', '/db/guillotina/', data=json.dumps({ '@type': 'Item', '@behaviors': [IMultiAttachment.__identifier__], 'id': 'foobar' }) ) assert status == 201 response, status = await requester( 'PATCH', '/db/guillotina/foobar/@upload/files/key1', data=b'X' * 1024 * 1024 * 10, headers={ 'x-upload-size': str(1024 * 1024 * 10) } ) assert status == 200 response, status = await requester( 'PATCH', '/db/guillotina/foobar/@upload/files/key2', data=b'Y' * 1024 * 1024 * 10, headers={ 'x-upload-size': str(1024 * 1024 * 10) } ) assert status == 200 response, status = await requester( 'GET', '/db/guillotina/foobar/@download/files/key1' ) assert status == 200 assert response == b'X' * 1024 * 1024 * 10 response, status = await requester( 'GET', '/db/guillotina/foobar/@download/files/key2' ) assert status == 200 assert response == b'Y' * 1024 * 1024 * 10 request = utils.get_mocked_request(requester.db) root = await utils.get_root(request) async with managed_transaction(request=request, abort_when_done=True): container = await root.async_get('guillotina') obj = await container.async_get('foobar') behavior = IMultiAttachment(obj) await behavior.load() assert behavior.files['key1']._blob.chunks == 2 assert behavior.files['key2']._blob.chunks == 2
async def test_create_blob(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): container = await create_content_in_container( db, 'Container', 'container', request=request, title='Container') blob = Blob(container) container.blob = blob async with managed_transaction(request=request): container = await db.async_get('container') assert blob.bid == container.blob.bid assert blob.resource_zoid == container._p_oid await db.async_del('container')
async def get_container(requester=None, request=None, tm=None): if request is None and requester is not None: request = get_mocked_request(requester.db) root = await get_root(request, tm) async with managed_transaction(request=request, tm=tm): container = await root.async_get('guillotina') if request is not None: request._container_id = container.id request.container = container return container
async def get_container(requester=None, request=None, container_id='guillotina'): if request is None: request = utils.get_mocked_request(requester.db) root = await utils.get_root(request) async with managed_transaction(request=request): container = await root.async_get(container_id) request._container_id = container.id request.container = container return container
async def test_create_blob(postgres, guillotina_main): root = get_utility(IApplication, name='root') db = root['db'] request = get_mocked_request(db) login(request) async with managed_transaction(request=request): container = await create_content_in_container( db, 'Container', 'container', request=request, title='Container') blob = Blob(container) container.blob = blob async with managed_transaction(request=request): container = await db.async_get('container') assert blob.bid == container.blob.bid assert blob.resource_zoid == container._p_oid await db.async_del('container')
async def run(self): try: if self._request is not None: aiotask_context.set('request', self._request) async with managed_transaction(request=self._request, abort_when_done=False): await self._func(*self._args or [], **self._kwargs or {}) else: # if no request, we do it without transaction await self._func(*self._args or [], **self._kwargs or {}) finally: aiotask_context.set('request', None)
async def run(self): try: if self._request is not None: aiotask_context.set('request', self._request) async with managed_transaction( request=self._request, abort_when_done=False): await self._func(*self._args or [], **self._kwargs or {}) else: # if no request, we do it without transaction await self._func(*self._args or [], **self._kwargs or {}) finally: aiotask_context.set('request', None)
async def test_tus(container_requester): async with container_requester as requester: response, status = await requester( 'POST', '/db/guillotina/', data=json.dumps({ '@type': 'Item', '@behaviors': ['guillotina.behaviors.attachment.IAttachment'], 'id': 'foobar' }) ) assert status == 201 response, status = await requester( 'POST', '/db/guillotina/foobar/@tusupload/file', headers={ 'UPLOAD-LENGTH': str(1024 * 1024 * 10), 'TUS-RESUMABLE': '1.0.0' } ) assert status == 201 for idx in range(10): # 10, 1mb chunks response, status = await requester( 'PATCH', '/db/guillotina/foobar/@tusupload/file', headers={ 'CONTENT-LENGTH': str(1024 * 1024 * 1), 'TUS-RESUMABLE': '1.0.0', 'upload-offset': str(1024 * 1024 * idx) }, data=b'X' * 1024 * 1024 * 1 ) assert status == 200 response, status = await requester( 'GET', '/db/guillotina/foobar/@download/file' ) assert status == 200 assert len(response) == (1024 * 1024 * 10) request = utils.get_mocked_request(requester.db) root = await utils.get_root(request) async with managed_transaction(request=request, abort_when_done=True): container = await root.async_get('guillotina') obj = await container.async_get('foobar') behavior = IAttachment(obj) await behavior.load() assert behavior.file._blob.chunks == 10
async def test_put_content(container_requester): async with container_requester as requester: data = 'WFhY' * 1024 + 'WA==' _, status = await requester('POST', '/db/guillotina/', data=json.dumps({ "@type": "Item", "title": "Item1", "id": "item1", "@behaviors": [IAttachment.__identifier__], IDublinCore.__identifier__: { "title": "foo", "description": "bar", "tags": ["one", "two"] }, IAttachment.__identifier__: { 'file': { 'filename': 'foobar.jpg', 'content-type': 'image/jpeg', 'encoding': 'base64', 'data': data } } })) assert status == 201 _, status = await requester('PUT', '/db/guillotina/item1', data=json.dumps({ "@behaviors": [IAttachment.__identifier__], IDublinCore.__identifier__: { "title": "foobar" } })) resp, status = await requester('GET', '/db/guillotina/item1') assert resp[IDublinCore.__identifier__]['tags'] is None assert resp[IAttachment.__identifier__]['file'] is None request = utils.get_mocked_request(requester.db) root = await utils.get_root(request) async with managed_transaction(request=request, abort_when_done=True): container = await root.async_get('guillotina') obj = await container.async_get('item1') assert obj.title == 'foobar' with pytest.raises(AttributeError): obj.description
async def create_next_index(self): async with managed_transaction(self.request, write=True, adopt_parent_txn=True) as txn: await txn.refresh(await self.index_manager.get_registry()) next_index_name = await self.index_manager.start_migration() if await self.conn.indices.exists(next_index_name): if self.force: # delete and recreate self.response.write('Clearing index') resp = await self.conn.indices.delete(next_index_name) assert resp['acknowledged'] await self.utility.create_index(next_index_name, self.index_manager) return next_index_name
async def test_managed_transaction_with_adoption(container_requester): async with container_requester as requester: request = utils.get_mocked_request(requester.db) root = await utils.get_root(request) async with managed_transaction(request=request, abort_when_done=True): container = await root.async_get('guillotina') container.title = 'changed title' container._p_register() assert container._p_oid in container._p_jar.modified # nest it with adoption async with managed_transaction(request=request, adopt_parent_txn=True): # this should commit, take on parent txn for container pass # no longer modified, adopted in previous txn assert container._p_oid not in container._p_jar.modified # finally, retrieve it again and make sure it's updated async with managed_transaction(request=request, abort_when_done=True): container = await root.async_get('guillotina') assert container.title == 'changed title'
async def test_write_blob_data(postgres, guillotina_main): root = get_utility(IApplication, name='root') db = root['db'] request = get_mocked_request(db) login(request) async with managed_transaction(request=request): container = await create_content_in_container( db, 'Container', 'container', request=request, title='Container') blob = Blob(container) container.blob = blob blobfi = blob.open('w') await blobfi.async_write(b'foobar') async with managed_transaction(request=request): container = await db.async_get('container') assert await container.blob.open().async_read() == b'foobar' assert container.blob.size == 6 assert container.blob.chunks == 1 await db.async_del('container')
async def test_create_content(container_requester): async with container_requester as requester: _, status = await requester('POST', '/db/guillotina/', data=json.dumps({ "@type": "Item", "title": "Item1", "id": "item1" })) assert status == 201 request = utils.get_mocked_request(requester.db) root = await utils.get_root(request) async with managed_transaction(request=request, abort_when_done=True): container = await root.async_get('guillotina') obj = await container.async_get('item1') assert obj.title == 'Item1'
async def migrate(self, db): migrations = sorted( get_utilities_for(IMigration)) self.request._tm = db.get_transaction_manager() async with managed_transaction(self.request, write=True) as txn: # make sure to get fresh copy txn._manager._hard_cache.clear() root = await db.get_root() current_version = StrictVersion(root.migration_version) for version, migration in migrations: if StrictVersion(version) > current_version: logger.warning(f'Starting migration on db {version}: {db.id}') await migration(db) logger.warning(f'Finished migration on db {version}: {db.id}') root.migration_version = version txn.register(root)
async def migrate(self, db): migrations = sorted(get_utilities_for(IMigration)) self.request._tm = db.get_transaction_manager() async with managed_transaction(self.request, write=True) as txn: # make sure to get fresh copy txn._manager._hard_cache.clear() root = await db.get_root() current_version = StrictVersion(root.migration_version) for version, migration in migrations: if StrictVersion(version) > current_version: logger.warning( f'Starting migration on db {version}: {db.id}') await migration(db) logger.warning( f'Finished migration on db {version}: {db.id}') root.migration_version = version txn.register(root)
async def cancel_migration(self): # canceling the migration, clearing index self.response.write('Canceling migration') async with managed_transaction(self.request, write=True, adopt_parent_txn=True): await self.utility.disable_next_index(self.context, request=self.request) self.response.write('Next index disabled') if self.active_task_id is not None: self.response.write('Canceling copy of index task') conn_es = await self.conn.transport.get_connection() async with conn_es._session.post( str(conn_es._base_url) + '_tasks/' + self.active_task_id + '/_cancel'): asyncio.sleep(5) if self.work_index_name: self.response.write('Deleting new index') await self.conn.indices.delete(self.work_index_name) self.response.write('Migration canceled')
async def cancel_migration(self): # canceling the migration, clearing index self.response.write('Canceling migration') async with managed_transaction(self.request, write=True, adopt_parent_txn=True): await self.index_manager.cancel_migration() self.response.write('Next index disabled') if self.active_task_id is not None: self.response.write('Canceling copy of index task') conn_es = await self.conn.transport.get_connection() async with conn_es.session.post( join(str(conn_es.base_url), '_tasks', self.active_task_id, '_cancel'), headers={'Content-Type': 'application/json'}): await asyncio.sleep(5) if self.work_index_name: self.response.write('Deleting new index') await self.conn.indices.delete(self.work_index_name) self.response.write('Migration canceled')
async def test_apply_next_index_does_not_cause_conflict_error(es_requester): async with es_requester as requester: container, req, txn, tm = await setup_txn_on_container(requester) search = getUtility(ICatalogUtility) migrator = Migrator(search, container, force=True, request=req) await migrator.setup_next_index() assert migrator.next_index_version == 2 assert migrator.work_index_name == 'guillotina-guillotina_2' container, req, txn, tm = await setup_txn_on_container(requester) annotations_container = IAnnotations(container) container_settings = await annotations_container.async_get( REGISTRY_DATA_KEY) container_settings['foo'] = 'bar' await tm.commit(txn=txn) async with managed_transaction(migrator.request, write=True, adopt_parent_txn=True) as txn: await migrator.utility.apply_next_index(migrator.container, migrator.request)
async def test_sharing_roleperm(container_requester): async with container_requester as requester: response, status = await requester('POST', '/db/guillotina/@sharing', data=json.dumps({ 'roleperm': [{ 'permission': 'guillotina.ViewContent', 'role': 'guillotina.Reader', 'setting': 'AllowSingle' }] })) assert status == 200 request = utils.get_mocked_request(requester.db) root = await utils.get_root(request) async with managed_transaction(request=request, abort_when_done=True): container = await root.async_get('guillotina') assert 'guillotina.Reader' in container.__acl__['roleperm']._bycol
async def test_copy_file_ob(container_requester): async with container_requester as requester: _, status = await requester( 'POST', '/db/guillotina/', data=json.dumps({ '@type': 'Item', '@behaviors': [IAttachment.__identifier__], 'id': 'foobar' }) ) assert status == 201 response, status = await requester( 'PATCH', '/db/guillotina/foobar/@upload/file', data=b'X' * 1024 * 1024 * 4, headers={ 'x-upload-size': str(1024 * 1024 * 4) } ) assert status == 200 request = utils.get_mocked_request(requester.db) root = await utils.get_root(request) async with managed_transaction(request=request, abort_when_done=True): container = await root.async_get('guillotina') obj = await container.async_get('foobar') attachment = IAttachment(obj) await attachment.load() existing_bid = attachment.file._blob.bid cfm = get_multi_adapter( (obj, request, IAttachment['file'].bind(attachment)), IFileManager ) from_cfm = get_multi_adapter( (obj, request, IAttachment['file'].bind(attachment)), IFileManager ) await cfm.copy(from_cfm) assert existing_bid != attachment.file._blob.bid
async def get_root(request): async with managed_transaction(request=request): return await request._tm.get_root()
async def test_set_local_guillotina(container_requester): async with container_requester as requester: response, status = await requester('POST', '/db/guillotina/@sharing', data=json.dumps({ 'prinperm': [{ 'principal': 'user1', 'permission': 'guillotina.AccessContent', 'setting': 'AllowSingle' }] })) assert status == 200 response, status = await requester('POST', '/db/guillotina/', data=json.dumps({ '@type': 'Item', 'id': 'testing' })) assert status == 201 response, status = await requester('GET', '/db/guillotina/testing/@sharing') assert len(response['inherit']) == 1 assert response['inherit'][0]['prinrole']['root'][ 'guillotina.ContainerAdmin'] == 'Allow' assert response['inherit'][0]['prinrole']['root'][ 'guillotina.Owner'] == 'Allow' assert 'Anonymous User' not in response['inherit'][0]['prinrole'] assert response['inherit'][0]['prinperm']['user1'][ 'guillotina.AccessContent'] == 'AllowSingle' # noqa request = utils.get_mocked_request(requester.db) root = await utils.get_root(request) async with managed_transaction(request=request, abort_when_done=True): container = await root.async_get('guillotina') testing_object = await container.async_get('testing') # Check the access users/roles principals = get_principals_with_access_content( testing_object, request) assert principals == ['root'] roles = get_roles_with_access_content(testing_object, request) assert roles == [ 'guillotina.Reader', 'guillotina.Reviewer', 'guillotina.Owner', 'guillotina.Editor', 'guillotina.ContainerAdmin' ] data = settings_for_object(testing_object) assert 'testing' in data[0] # Now we add the user1 with inherit on the container response, status = await requester('POST', '/db/guillotina/@sharing', data=json.dumps({ 'prinperm': [{ 'principal': 'user1', 'permission': 'guillotina.AccessContent', 'setting': 'Allow' }] })) root = await utils.get_root(request) async with managed_transaction(request=request, abort_when_done=True): # need to retreive objs again from db since they changed container = await root.async_get('guillotina') testing_object = await container.async_get('testing') principals = get_principals_with_access_content( testing_object, request) assert len(principals) == 2 assert 'user1' in principals # Now we add the user1 with deny on the object response, status = await requester('POST', '/db/guillotina/testing/@sharing', data=json.dumps({ 'prinperm': [{ 'principal': 'user1', 'permission': 'guillotina.AccessContent', 'setting': 'Deny' }] })) # need to retreive objs again from db since they changed root = await utils.get_root(request) async with managed_transaction(request=request, abort_when_done=True): container = await root.async_get('guillotina') testing_object = await container.async_get('testing') principals = get_principals_with_access_content( testing_object, request) assert principals == ['root']
def transaction(self, **kwargs): return managed_transaction(tm=self, **kwargs)
async def get_root(request=None, tm=None): async with managed_transaction(request=request, tm=tm) as txn: return await txn.manager.get_root()
async def test_tus_unknown_size(container_requester): async with container_requester as requester: response, status = await requester('POST', '/db/guillotina/', data=json.dumps({ '@type': 'Item', '@behaviors': [IAttachment.__identifier__], 'id': 'foobar' })) assert status == 201 response, status = await requester( 'OPTIONS', '/db/guillotina/foobar/@tusupload/file', headers={ 'Origin': 'http://foobar.com', 'Access-Control-Request-Method': 'POST' }) assert status == 200 response, status = await requester( 'POST', '/db/guillotina/foobar/@tusupload/file', headers={ 'Upload-Defer-Length': '1', 'TUS-RESUMABLE': '1.0.0' }) assert status == 201 response, status = await requester( 'HEAD', '/db/guillotina/foobar/@tusupload/file') assert status == 200 offset = 0 for idx in range(10): # random sizes size = 1024 * random.choice([1024, 1243, 5555, 7777]) response, status = await requester( 'PATCH', '/db/guillotina/foobar/@tusupload/file', headers={ 'TUS-RESUMABLE': '1.0.0', 'upload-offset': str(offset) }, data=b'X' * size) offset += size assert status == 200 response, status = await requester( 'PATCH', '/db/guillotina/foobar/@tusupload/file', headers={ 'TUS-RESUMABLE': '1.0.0', 'upload-offset': str(offset), 'UPLOAD-LENGTH': str(offset) # finish it }, data=b'') response, status = await requester( 'GET', '/db/guillotina/foobar/@download/file') assert status == 200 assert len(response) == offset request = utils.get_mocked_request(requester.db) root = await utils.get_root(request) async with managed_transaction(request=request, abort_when_done=True): container = await root.async_get('guillotina') obj = await container.async_get('foobar') behavior = IAttachment(obj) await behavior.load() assert behavior.file._blob.size == offset
async def test_tus_unknown_size(container_requester): async with container_requester as requester: response, status = await requester( 'POST', '/db/guillotina/', data=json.dumps({ '@type': 'Item', '@behaviors': [IAttachment.__identifier__], 'id': 'foobar' }) ) assert status == 201 response, status = await requester( 'OPTIONS', '/db/guillotina/foobar/@tusupload/file', headers={ 'Origin': 'http://foobar.com', 'Access-Control-Request-Method': 'POST' }) assert status == 200 response, status = await requester( 'POST', '/db/guillotina/foobar/@tusupload/file', headers={ 'Upload-Defer-Length': '1', 'TUS-RESUMABLE': '1.0.0' } ) assert status == 201 response, status = await requester( 'HEAD', '/db/guillotina/foobar/@tusupload/file') assert status == 200 offset = 0 for idx in range(10): # random sizes size = 1024 * random.choice([1024, 1243, 5555, 7777]) response, status = await requester( 'PATCH', '/db/guillotina/foobar/@tusupload/file', headers={ 'TUS-RESUMABLE': '1.0.0', 'upload-offset': str(offset) }, data=b'X' * size ) offset += size assert status == 200 response, status = await requester( 'PATCH', '/db/guillotina/foobar/@tusupload/file', headers={ 'TUS-RESUMABLE': '1.0.0', 'upload-offset': str(offset), 'UPLOAD-LENGTH': str(offset) # finish it }, data=b'' ) response, status = await requester( 'GET', '/db/guillotina/foobar/@download/file' ) assert status == 200 assert len(response) == offset request = utils.get_mocked_request(requester.db) root = await utils.get_root(request) async with managed_transaction(request=request, abort_when_done=True): container = await root.async_get('guillotina') obj = await container.async_get('foobar') behavior = IAttachment(obj) await behavior.load() assert behavior.file._blob.size == offset
async def run_migration(self): alias_index_name = await self.index_manager.get_index_name() existing_index = await self.index_manager.get_real_index_name() await self.setup_next_index() self.mapping_diff = await self.calculate_mapping_diff() diff = json.dumps(self.mapping_diff, sort_keys=True, indent=4, separators=(',', ': ')) self.response.write(f'Caculated mapping diff: {diff}') if not self.full: # if full, we're reindexing everything does not matter what # anyways, so skip self.response.write(f'Copying initial index {existing_index} ' f'into {self.work_index_name}') try: await self.copy_to_next_index() self.response.write('Copying initial index data finished') except elasticsearch.exceptions.NotFoundError: self.response.write('No initial index to copy to') if not self.mapping_only: try: self.existing = await self.get_all_uids() except elasticsearch.exceptions.NotFoundError: pass self.index_start_time = time.time() if self.children_only or IContainer.providedBy(self.context): await self.process_folder(self.context) # this is recursive else: await self.process_object(self.context) # this is recursive await self.check_existing() await self.flush() await self.join_futures() async with get_migration_lock(await self.index_manager.get_index_name()): self.response.write('Activating new index') async with managed_transaction(self.request, write=True, adopt_parent_txn=True): await self.index_manager.finish_migration() self.status = 'done' self.response.write(f'''Update alias({alias_index_name}): {existing_index} -> {self.work_index_name} ''') try: await self.conn.indices.update_aliases({ "actions": [{ "remove": { "alias": alias_index_name, "index": existing_index } }, { "add": { "alias": alias_index_name, "index": self.work_index_name } }] }) except elasticsearch.exceptions.NotFoundError: await self.conn.indices.update_aliases({ "actions": [{ "add": { "alias": alias_index_name, "index": self.work_index_name } }] }) try: await self.conn.indices.close(existing_index) await self.conn.indices.delete(existing_index) self.response.write('Old index deleted') except elasticsearch.exceptions.NotFoundError: pass if len(self.sub_indexes) > 0: self.response.write( f'Migrating sub indexes: {len(self.sub_indexes)}') for ob in self.sub_indexes: im = get_adapter(ob, IIndexManager) migrator = Migrator(self.utility, ob, response=self.response, force=self.force, log_details=self.log_details, memory_tracking=self.memory_tracking, request=self.request, bulk_size=self.bulk_size, full=self.full, reindex_security=self.reindex_security, mapping_only=self.mapping_only, index_manager=im, children_only=True) self.response.write(f'Migrating index for: {ob}') await migrator.run_migration()
async def test_tus_with_empty_file(container_requester): async with container_requester as requester: response, status = await requester( 'POST', '/db/guillotina/', data=json.dumps({ '@type': 'Item', '@behaviors': [IAttachment.__identifier__], 'id': 'foobar' }) ) assert status == 201 response, status = await requester( 'OPTIONS', '/db/guillotina/foobar/@tusupload/file', headers={ 'Origin': 'http://foobar.com', 'Access-Control-Request-Method': 'POST' }) assert status == 200 response, status = await requester( 'POST', '/db/guillotina/foobar/@tusupload/file', headers={ 'UPLOAD-LENGTH': '0', 'TUS-RESUMABLE': '1.0.0' } ) assert status == 201 response, status = await requester( 'HEAD', '/db/guillotina/foobar/@tusupload/file') assert status == 200 response, status = await requester( 'PATCH', '/db/guillotina/foobar/@tusupload/file', headers={ 'CONTENT-LENGTH': '0', 'TUS-RESUMABLE': '1.0.0', 'upload-offset': '0' }, data=b'' ) assert status == 200 response, status = await requester( 'GET', '/db/guillotina/foobar/@download/file' ) assert status == 200 assert len(response) == 0 request = utils.get_mocked_request(requester.db) root = await utils.get_root(request) async with managed_transaction(request=request, abort_when_done=True): container = await root.async_get('guillotina') obj = await container.async_get('foobar') behavior = IAttachment(obj) await behavior.load() assert behavior.file._blob.chunks == 0