Skip to content

Commit

Permalink
Merge pull request #82 from OnroerendErfgoed/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
claeyswo authored Jun 9, 2020
2 parents 2a591a8 + b2fffb3 commit 70b406f
Show file tree
Hide file tree
Showing 12 changed files with 116 additions and 43 deletions.
8 changes: 1 addition & 7 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,10 @@ language: python
sudo: false
python:
- "2.7"
- "3.5"
- "3.6"
env:
- PROJECT=augeias
notifications:
email:
- [email protected]
- [email protected]
- [email protected]
install:
install:
- pip install -r requirements-dev.txt
- python setup.py develop
script:
Expand Down
5 changes: 5 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
0.6.0 (09-06-2020)
------------------

- Lijst met vertaling van id naar bestandsnaam meesturen download zip (#80)

0.5.0 (28-11-2018)
------------------

Expand Down
2 changes: 1 addition & 1 deletion augeias/stores/CephStore.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def delete_object(self, container_key, object_key):
def update_object(self, container_key, object_key, object_data):
pass

def get_container_data(self, container_key):
def get_container_data(self, container_key, translations=None):
pass

def create_container(self, container_key):
Expand Down
13 changes: 9 additions & 4 deletions augeias/stores/PairTreeFileSystemStore.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,19 +116,24 @@ def delete_object(self, container_key, object_key):
except PartNotFoundException:
raise NotFoundException

def get_container_data(self, container_key):
'''
def get_container_data(self, container_key, translations=None):
"""
Find a container and return a zip file of its contents.
:param container_key: Key of the container which must be retrieved.
:param translations: Dict of object IDs and file names to use for them.
:return: a zip file containing all files of the container.
'''
"""
translations = translations or {}
container = self.store.get_object(container_key,
create_if_doesnt_exist=False)
in_memory_file = BytesIO()
with ZipFile(in_memory_file, 'w') as zf:
for object_key in container.list_parts():
zf.writestr(object_key, container.get_bytestream(object_key))
zf.writestr(
translations.get(object_key, object_key),
container.get_bytestream(object_key)
)
in_memory_file.seek(0)
return in_memory_file

Expand Down
4 changes: 3 additions & 1 deletion augeias/stores/StoreInterface.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from abc import ABCMeta, abstractmethod


class IStore:
'''
This interface handles object-storage.
Expand Down Expand Up @@ -77,11 +78,12 @@ def list_object_keys_for_container(self, container_key):
'''

@abstractmethod
def get_container_data(self, container_key):
def get_container_data(self, container_key, translations=None):
'''
Find a container and return a zip file of its contents.
:param container_key: Key of the container which must be retrieved.
:param translations: Dict of object IDs and file names to use for them.
:return: a zip file containing all files of the container.
'''
@abstractmethod
Expand Down
7 changes: 5 additions & 2 deletions augeias/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,13 @@ def list_object_keys_for_container(self):

@view_config(route_name='get_container_data', permission='view')
def get_container_data(self):
'''get a container from the data store'''
"""Get a container from the data store as zip."""
parameters = self.request.GET
collection = _retrieve_collection(self.request)
container_key = self.request.matchdict['container_key']
zip_file = collection.object_store.get_container_data(container_key)
zip_file = collection.object_store.get_container_data(
container_key, translations=parameters
)
filename = str(container_key) + '.zip'
disposition = ('attachment; filename={}'.format(filename))
res = Response(content_type='application/zip', status=200,
Expand Down
25 changes: 11 additions & 14 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,24 @@
--requirement requirements.txt

# pyramid
pyramid-debugtoolbar==4.5
pyramid-debugtoolbar==4.6.1

# Testing
pytest==3.8.1
pytest-cov==2.6.0
py==1.6.0
coveralls==1.5.1
webtest==2.0.30
mock==2.0.0
pytest==5.4.3; python_version > '3.0'
pytest==4.6.11; python_version < '3.0'
pytest-cov==2.9.0
mock==3.0.5; python_version < '3.0'
tempdir==0.7.1
webtest==2.0.35

# Documentation
Sphinx==1.8.1
Sphinx==3.1.0; python_version > '3.0'
Sphinx==1.8.5; python_version < '3.0'
sphinxcontrib-httpdomain==1.7.0
sphinx_rtd_theme==0.4.1
sphinx_rtd_theme==0.4.3

# waitress
waitress==1.1.0
waitress==1.4.4

# Linting
flake8==3.5.0
mccabe==0.6.1
pep8==1.7.1
pyflakes==2.0.0
flake8==3.8.3
11 changes: 1 addition & 10 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,17 +1,8 @@
# pyramid
pyramid==1.9.2
pyramid==1.10.4
pyramid_rewrite==0.2

# pairtree
ez_setup==0.9
pairtree==0.8.1
python-magic==0.4.15

venusian==1.1.0
webob==1.8.2
PasteDeploy==1.5.2

repoze.lru==0.7
zope.deprecation==4.3.0
zope.interface==4.5.0
translationstring==1.3
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
]

setup(name='augeias',
version='0.5.0',
version='0.6.0',
description='Augeias. Stores your files.',
long_description=README + '\n\n' + HISTORY,
classifiers=[
Expand Down
12 changes: 11 additions & 1 deletion tests/test_functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ def test_create_container(self):
self.assertIn('TEST_CONTAINER_ID', res.text)
self.assertIn(self.storage_location + 'collections/TEST_COLLECTION/containers/TEST_CONTAINER_ID', res.text)


def test_add_object(self):
# create a container
cres = self.testapp.put('/collections/TEST_COLLECTION/containers/TEST_CONTAINER_ID')
Expand Down Expand Up @@ -188,6 +187,17 @@ def test_download_container_zip(self):
self.assertIn('200x300', filenames)
self.assertIn('400x600', filenames)

res = self.testapp.get(
'/collections/TEST_COLLECTION/containers/TEST_CONTAINER_ID?200x300=file1.pdf',
headers={'Accept': 'application/zip'}
)
self.assertEqual('200 OK', res.status)
with ZipFile(BytesIO(res.body)) as zf:
filenames = zf.namelist()
self.assertEqual(2, len(filenames))
self.assertIn('file1.pdf', filenames)
self.assertIn('400x600', filenames)


def test_update_object(self):
# create container and add object
Expand Down
22 changes: 22 additions & 0 deletions tests/test_stores.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import os
import unittest
from zipfile import ZipFile

import tempdir
from augeias.stores.CephStore import CephStore
from augeias.stores.PairTreeFileSystemStore import PairTreeFileSystemStore, _is_allowed_data, _validate_data
Expand Down Expand Up @@ -93,6 +95,26 @@ def test_add_object_to_nonexisting_container(self):
error_raised = True
self.assertTrue(error_raised)

def test_get_container_data(self):
container_key = 'container'
self.store.create_container(container_key)
self.store.create_object(container_key, 'object_key', b'file-data')

zip_file = self.store.get_container_data(container_key)
with ZipFile(zip_file) as zf:
filenames = zf.namelist()
self.assertEqual(1, len(filenames))
self.assertIn('object_key', filenames)

zip_file = self.store.get_container_data(
container_key,
translations={'object_key': 'filename.pdf'}
)
with ZipFile(zip_file) as zf:
filenames = zf.namelist()
self.assertEqual(1, len(filenames))
self.assertIn('filename.pdf', filenames)

def test_delete_container(self):
self.store.create_container('x')
self.store.delete_container('x')
Expand Down
48 changes: 46 additions & 2 deletions tests/test_views.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import unittest

from pyramid import testing

from augeias.views import AugeiasView

try:
from unittest.mock import Mock
except ImportError:
from mock import Mock # pragma: no cover
from pyramid import testing
from augeias.views import AugeiasView


class ViewTests(unittest.TestCase):
Expand All @@ -21,3 +24,44 @@ def tearDown(self):
def test_my_view(self):
info = self.view.my_view()
self.assertEqual(info['project'], 'augeias')

def test_get_container_data(self):
collection = Mock()
collection.object_store.get_container_data.return_value = Mock(
read=Mock(return_value=b'zip-file')
)
self.request.registry.collections = {'collection': collection}
self.request.matchdict = {
'container_key': 'container',
'collection_key': 'collection'
}
response = self.view.get_container_data()
self.assertEqual(b'zip-file', response.body)

def test_get_container_data_translations(self):
collection = Mock()
collection.object_store.get_container_data.return_value = Mock(
read=Mock(return_value=b'zip-file')
)
self.request.GET = {
'001': 'name1.pdf',
'002': 'name2.pdf',
}
self.request.registry.collections = {'collection': collection}
self.request.matchdict = {
'container_key': 'container',
'collection_key': 'collection'
}
response = self.view.get_container_data()
self.assertEqual(b'zip-file', response.body)
args, kwargs = collection.object_store.get_container_data.call_args_list[0]
self.assertEqual(args, ('container',))
self.assertEqual(
kwargs,
{
'translations': {
'001': 'name1.pdf',
'002': 'name2.pdf',
}
}
)

0 comments on commit 70b406f

Please sign in to comment.