Skip to content

Commit

Permalink
NXPY-63: Handle multiblob uploads to a single document
Browse files Browse the repository at this point in the history
  • Loading branch information
LKleinNux authored May 31, 2018
1 parent 52b61bf commit ca3a5b7
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 4 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,15 @@ Changelog
Release date: ``2018-05-31``

- `NXPY-58 <https://jira.nuxeo.com/browse/NXPY-58>`__: Modify the client to fit in Nuxeo Drive
-`NXPY-63 <https://jira.nuxeo.com/browse/NXPY-63>`__: Handle multiblob uploads to a single document

Technical changes
~~~~~~~~~~~~~~~~~

- Added ``Batch.attach()``
- Added ``Batch.execute()``
- Added nuxeo/uploads.py::\ ``attach()``
- Added nuxeo/uploads.py::\ ``execute()``

2.0.0
-----
Expand Down
5 changes: 4 additions & 1 deletion nuxeo/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,16 @@ def on_exit(self):
def query(
self,
query, # type: Text
params=None, # type: Dict[Text, Text]
params=None, # type: Dict[Text, Any]
):
"""
Query the server with the specified NXQL query.
Additional qery parameters can be set via the `params` argument:
>>> nuxeo.client.query('SQL query', params={'properties': '*'})
You can find what parameters to tweak under the `Repository.Query`
operation details.
"""

data = {'query': query}
Expand Down
28 changes: 27 additions & 1 deletion nuxeo/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,33 @@ def upload(self, blob, **kwargs):
:param kwargs: the upload settings
:return: the blob info
"""
return self.service.upload(self, blob, **kwargs)
blob = self.service.upload(self, blob, **kwargs)
self.blobs[self._upload_idx] = blob
self._upload_idx += 1
return blob

def execute(self, operation, file_idx=None, params=None):
# type: (Text, int, Dict[Text, Any]) -> Any
"""
Execute an operation on this batch.
:param operation: operation to execute
:param file_idx: target file of the operation
:param params: parameters of the operation
:return: the output of the operation
"""
return self.service.execute(self, operation, file_idx, params)

def attach(self, doc, file_idx=None):
# type: (Text) -> Any
"""
Attach one or all files of this batch to a document.
:param doc: document to attach
:param file_idx: target file
:return: the output of the attach operation
"""
return self.service.attach(self, doc, file_idx)


class Blob(Model):
Expand Down
35 changes: 34 additions & 1 deletion nuxeo/uploads.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,39 @@ def upload(self, batch, blob, chunked=False, limit=CHUNK_LIMIT):
blob.name, data, path, chunked, index, headers)
index += 1

batch._upload_idx += 1
response.batch_id = batch.uid
return response

def execute(self, batch, operation, file_idx=None, params=None):
# type: (Batch, Text, Optional[int], Optional[Dict[Text,Any]]) -> Any
"""
Execute an operation with the batch or one of its files as an input.
:param batch: input for the operation
:param operation: operation to execute
:param file_idx: if not None, sole input of the operation
:param params: parameters for the operation
:return: the output of the operation
"""
path = '{}/{}'.format(self.endpoint, batch.uid)
if file_idx is not None:
path = '{}/{}'.format(path, file_idx)

path = '{}/execute/{}'.format(path, operation)

return self.client.request('POST', path, data={'params': params})

def attach(self, batch, doc, file_idx=None):
# type: (Batch, Text, Optional[int]) -> Any
"""
Attach one or all files of a batch to a document.
:param batch: batch to attach
:param doc: document to attach
:param file_idx: if not None, only this file will be attached
:return: the output of the attach operation
"""
params = {'document': doc}
if file_idx is None and batch._upload_idx > 1:
params['xpath'] = 'files:files'
return self.execute(batch, 'Blob.Attach', file_idx, params)
17 changes: 17 additions & 0 deletions tests/test_batchupload.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,23 @@ def test_empty_file(chunked, server):
batch.upload(BufferBlob(data='', name='Test.txt'), chunked=chunked)


def test_execute(server):
server.client.set(schemas=['dublincore', 'file'])
doc = server.documents.create(new_doc, parent_path=pytest.ws_root_path)
try:
batch = get_batch(server)
assert not doc.properties['file:content']
batch.execute('Blob.AttachOnDocument', file_idx=0,
params={'document': pytest.ws_root_path + '/Document'})
doc = server.documents.get(path=pytest.ws_root_path + '/Document')
assert doc.properties['file:content']
blob = doc.fetch_blob()
assert isinstance(blob, bytes)
assert blob == b'data'
finally:
doc.delete()


def test_fetch(server):
batch = get_batch(server)
blob = batch.get(0)
Expand Down
47 changes: 46 additions & 1 deletion tests/test_document.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,41 @@

import pytest

from nuxeo.models import Document
from nuxeo.models import BufferBlob, Document


class Doc(object):

def __init__(self, server, blobs=0):
self.server = server
self.blobs = blobs

def __enter__(self):
doc = Document(
name=pytest.ws_python_test_name,
type='File',
properties={
'dc:title': 'bar.txt',
}
)
self.doc = self.server.documents.create(
doc, parent_path=pytest.ws_root_path)

if self.blobs:
# Upload several blobs for one document
batch = self.server.uploads.batch()
for idx in range(self.blobs):
blob = BufferBlob(
data='foo {}'.format(idx),
name='foo-{}.txt'.format(idx))
batch.upload(blob)

batch.attach(pytest.ws_root_path + '/' +
pytest.ws_python_test_name)
return self.doc

def __exit__(self, *args):
self.doc.delete()


def test_document_create(server):
Expand All @@ -25,6 +59,17 @@ def test_document_create(server):
assert not server.documents.exists(doc.uid)


def test_document_get_blobs(server):
""" Fetch all blobs of a given document. """

number = 4
with Doc(server, blobs=number) as doc:
for idx in range(number):
xpath = 'files:files/{}/file'.format(idx)
blob = doc.fetch_blob(xpath)
assert blob == 'foo {}'.format(idx)


def test_document_list_update(server):
new_doc1 = Document(
name='ws-js-tests1',
Expand Down

0 comments on commit ca3a5b7

Please sign in to comment.