diff --git a/MANIFEST.in b/MANIFEST.in index 34db2cc..8b91ad2 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,3 +1,4 @@ graft src/humulus/static graft src/humulus/templates +graft src/humulus/designs global-exclude *.pyc diff --git a/src/humulus/couch.py b/src/humulus/couch.py index 6a8ece4..f957316 100644 --- a/src/humulus/couch.py +++ b/src/humulus/couch.py @@ -14,9 +14,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -from datetime import datetime import json import uuid +from datetime import datetime +from pathlib import Path import click from cloudant import CouchDB @@ -54,6 +55,7 @@ def build_couch(): couch = get_couch() dbname = current_app.config['COUCH_DATABASE'] couch.create_database(dbname, throw_on_exists=False) + put_designs() @click.command('build-couch') @@ -121,11 +123,32 @@ def get_doc_or_404(id): return doc -def put_doc_from_file(filename): - """Loads filename and stores it in couch. +def put_designs(): + """Loads all design docs from the designs/ folder and puts them. - The file must be valid JSON. + If any documents are missing an '_id' field, a KeyError exception will have + been raised. Not all documents will have been loaded. """ - with open(filename, 'r') as doc: - response = put_doc(json.load(doc)) - return response + here = Path(__file__).parent + + for filename in here.glob('designs/*.json'): + with open(filename, 'r') as fp: + data = json.load(fp) + + # See if document already exists + if data['_id'] in get_db(): + doc = get_doc(data['_id']) + # Popping off the revision and storing it. Then compare + rev = doc.pop('_rev') + doc.pop('created', None) + if data == doc: + get_db().clear() + return + # Copy the values of data to doc. + for k in data: + doc[k] = data[k] + doc['_rev'] = rev # Add the revision back + print(doc) + doc.save() + else: + put_doc(data) diff --git a/src/humulus/designs/recipes.json b/src/humulus/designs/recipes.json new file mode 100644 index 0000000..3a12c30 --- /dev/null +++ b/src/humulus/designs/recipes.json @@ -0,0 +1,12 @@ +{ + "_id": "_design/recipes", + "language": "javascript", + "views": { + "by-date": { + "map": "function (doc) {\n if (doc.$type == \"recipe\" && doc.created && doc.name) {\n emit(doc.created, doc.name)\n }\n}" + } + }, + "lists": {}, + "indexes": {}, + "shows": {} + } diff --git a/tests/assets/changed/designs/recipes.json b/tests/assets/changed/designs/recipes.json new file mode 100644 index 0000000..3a12c30 --- /dev/null +++ b/tests/assets/changed/designs/recipes.json @@ -0,0 +1,12 @@ +{ + "_id": "_design/recipes", + "language": "javascript", + "views": { + "by-date": { + "map": "function (doc) {\n if (doc.$type == \"recipe\" && doc.created && doc.name) {\n emit(doc.created, doc.name)\n }\n}" + } + }, + "lists": {}, + "indexes": {}, + "shows": {} + } diff --git a/tests/assets/initial/designs/recipes.json b/tests/assets/initial/designs/recipes.json new file mode 100644 index 0000000..4cb6650 --- /dev/null +++ b/tests/assets/initial/designs/recipes.json @@ -0,0 +1,8 @@ +{ + "_id": "_design/recipes", + "language": "javascript", + "views": {}, + "lists": {}, + "indexes": {}, + "shows": {} + } diff --git a/tests/assets/test_doc.json b/tests/assets/test_doc.json deleted file mode 100644 index 01c89e3..0000000 --- a/tests/assets/test_doc.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "_id": "testfile", - "foo": "bar" -} diff --git a/tests/test_couch.py b/tests/test_couch.py index b248b4f..127add2 100644 --- a/tests/test_couch.py +++ b/tests/test_couch.py @@ -12,10 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -import pathlib import uuid +from pathlib import Path -from humulus.couch import get_doc, put_doc, update_doc, put_doc_from_file +from humulus.couch import get_doc, put_doc, update_doc, put_designs def test_put_doc(app): @@ -67,9 +67,26 @@ def test_get_doc(app): assert get_doc('foobar')['data'] == 'test' -def test_put_doc_from_file(app): - here = pathlib.Path(__file__).parent +def test_put_designs(app, monkeypatch): + # Always return the path to our test assets + testpath = Path(__file__).parent + with app.app_context(): - response = put_doc_from_file(here/'assets'/'test_doc.json') - assert response['_id'] == 'testfile' - assert response['foo'] == 'bar' + # Test initial load of designs + monkeypatch.setattr(Path, 'parent', testpath/'assets/initial') + put_designs() + + recipes = get_doc('_design/recipes') + assert 'language' in recipes + rev = recipes['_rev'] + + # Try again, make sure nothing changed. + put_designs() + recipes = get_doc('_design/recipes') + assert recipes['_rev'] == rev + + # Test that changes can be loaded + monkeypatch.setattr(Path, 'parent', testpath/'assets/changed') + put_designs() + recipes = get_doc('_design/recipes') + assert 'by-date' in recipes['views']