Skip to content

Commit

Permalink
Merge pull request #55 from OnroerendErfgoed/DEV_0.5.0
Browse files Browse the repository at this point in the history
Dev 0.5.0
  • Loading branch information
claeyswo authored Nov 28, 2018
2 parents 2940114 + ee3b661 commit 2a591a8
Show file tree
Hide file tree
Showing 12 changed files with 99 additions and 14 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ sudo: false
python:
- "2.7"
- "3.5"
- "3.6"
env:
- PROJECT=augeias
notifications:
Expand Down
6 changes: 6 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
0.5.0 (28-11-2018)
------------------

- Download zip of entire container (#48)
- Update list of supported python version (#51)

0.4.1 (26-10-2017)
------------------

Expand Down
6 changes: 5 additions & 1 deletion augeias/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ def includeme(config):
config.add_route('delete_container', pattern='/collections/{collection_key}/containers/{container_key}',
request_method="DELETE")
config.add_route('list_object_keys_for_container',
pattern='/collections/{collection_key}/containers/{container_key}', request_method="GET")
pattern='/collections/{collection_key}/containers/{container_key}', request_method="GET",
accept='application/json')
config.add_route('get_container_data',
pattern='/collections/{collection_key}/containers/{container_key}',
request_method="GET", accept='application/zip')
config.add_route('create_object_and_id', pattern='/collections/{collection_key}/containers/{container_key}',
request_method="POST")
config.add_route('update_object', pattern='/collections/{collection_key}/containers/{container_key}/{object_key}',
Expand Down
3 changes: 3 additions & 0 deletions augeias/stores/CephStore.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ 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):
pass

def create_container(self, container_key):
pass

Expand Down
18 changes: 18 additions & 0 deletions augeias/stores/PairTreeFileSystemStore.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
'''
This module provide a simple filesystem based store
'''
from io import BytesIO
from zipfile import ZipFile

from pairtree import PairtreeStorageFactory, PartNotFoundException, ObjectNotFoundException, id2path
from augeias.stores.StoreInterface import IStore
Expand Down Expand Up @@ -114,6 +116,22 @@ def delete_object(self, container_key, object_key):
except PartNotFoundException:
raise NotFoundException

def get_container_data(self, container_key):
'''
Find a container and return a zip file of its contents.
:param container_key: Key of the container which must be retrieved.
:return: a zip file containing all files of the container.
'''
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))
in_memory_file.seek(0)
return in_memory_file

def create_container(self, container_key):
'''
Create a new container in the data store.
Expand Down
8 changes: 8 additions & 0 deletions augeias/stores/StoreInterface.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,14 @@ def list_object_keys_for_container(self, container_key):
'''

@abstractmethod
def get_container_data(self, container_key):
'''
Find a container and return a zip file of its contents.
:param container_key: Key of the container which must be retrieved.
:return: a zip file containing all files of the container.
'''
@abstractmethod
def create_container(self, container_key):
'''
Create a new container in the data store.
Expand Down
13 changes: 13 additions & 0 deletions augeias/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,19 @@ def list_object_keys_for_container(self):
res.json_body = collection.object_store.list_object_keys_for_container(container_key)
return res

@view_config(route_name='get_container_data', permission='view')
def get_container_data(self):
'''get a container from the data store'''
collection = _retrieve_collection(self.request)
container_key = self.request.matchdict['container_key']
zip_file = collection.object_store.get_container_data(container_key)
filename = str(container_key) + '.zip'
disposition = ('attachment; filename={}'.format(filename))
res = Response(content_type='application/zip', status=200,
content_disposition=disposition)
res.body = zip_file.read()
return res

@view_config(route_name='create_container', permission='edit')
def create_container(self):
'''create a new container in the data store'''
Expand Down
18 changes: 9 additions & 9 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,21 @@
--requirement requirements.txt

# pyramid
pyramid-debugtoolbar==4.4
pyramid-debugtoolbar==4.5

# Testing
pytest==3.6.0
pytest-cov==2.5.1
py==1.5.3
coveralls==1.3.0
webtest==2.0.29
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
tempdir==0.7.1

# Documentation
Sphinx==1.7.5
sphinxcontrib-httpdomain==1.6.1
sphinx_rtd_theme==0.3.1
Sphinx==1.8.1
sphinxcontrib-httpdomain==1.7.0
sphinx_rtd_theme==0.4.1

# waitress
waitress==1.1.0
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pairtree==0.8.1
python-magic==0.4.15

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

repoze.lru==0.7
Expand Down
6 changes: 5 additions & 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.4.1',
version='0.5.0',
description='Augeias. Stores your files.',
long_description=README + '\n\n' + HISTORY,
classifiers=[
Expand All @@ -27,7 +27,11 @@
"Topic :: Internet :: WWW/HTTP",
"Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
],
python_requires='>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*',
author='Flanders Heritage Agency',
author_email='[email protected]',
url='https://augeias.readthedocs.org',
Expand Down
28 changes: 28 additions & 0 deletions tests/test_functional.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import os
import re
import unittest
from io import BytesIO
from zipfile import ZipFile

import tempdir
from pyramid.paster import get_appsettings
from webtest import TestApp
Expand Down Expand Up @@ -161,6 +164,31 @@ def test_list_object_keys_for_container(self):
l = [i.strip() for i in l]
self.assertTrue('200x300' in l and '400x600' in l)

def test_download_container_zip(self):
# create container and add objects
cres = self.testapp.put('/collections/TEST_COLLECTION/containers/TEST_CONTAINER_ID')
self.assertEqual('200 OK', cres.status)
testdata = os.path.join(here, '../', 'fixtures/kasteel.jpg')
with open(testdata, 'rb') as f:
bdata = f.read()
ores = self.testapp.put('/collections/TEST_COLLECTION/containers/TEST_CONTAINER_ID/200x300', bdata)
self.assertEqual('200 OK', ores.status)
testdata = os.path.join(here, '../', 'fixtures/brug.jpg')
with open(testdata, 'rb') as f:
bdata = f.read()
ores = self.testapp.put('/collections/TEST_COLLECTION/containers/TEST_CONTAINER_ID/400x600', bdata)
self.assertEqual('200 OK', ores.status)

res = self.testapp.get('/collections/TEST_COLLECTION/containers/TEST_CONTAINER_ID',
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('200x300', filenames)
self.assertIn('400x600', filenames)


def test_update_object(self):
# create container and add object
cres = self.testapp.put('/collections/TEST_COLLECTION/containers/TEST_CONTAINER_ID')
Expand Down
4 changes: 2 additions & 2 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[tox]
envlist = py27,py33,py34,cover
envlist = py27,py35,py36,py37,cover

[testenv]
deps =
Expand All @@ -12,7 +12,7 @@ commands =

[testenv:cover]
basepython =
python3.4
python3.5
deps =
pytest
pytest-cov
Expand Down

0 comments on commit 2a591a8

Please sign in to comment.