Skip to content

Commit 06bec55

Browse files
dholthdjc
authored andcommitted
add design doc from filesystem loader
1 parent f0230e6 commit 06bec55

File tree

2 files changed

+116
-0
lines changed

2 files changed

+116
-0
lines changed

couchdb/loader.py

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
#!/usr/bin/env python
2+
"""
3+
Load design documents from the filesystem into a dict.
4+
Subset of couchdbkit/couchapp functionality.
5+
6+
Description
7+
-----------
8+
9+
Convert a target directory into an object (dict).
10+
11+
Each filename (without extension) or subdirectory name is a key in this object.
12+
13+
For files, the utf-8-decoded contents are the value, except for .json files
14+
which are first decoded as json.
15+
16+
Subdirectories are converted into objects using the same procedure and then
17+
added to the parent object.
18+
19+
Typically used for design documents. This directory tree::
20+
21+
.
22+
├── filters
23+
│   └── forms_only.js
24+
├── _id
25+
├── language
26+
├── lib
27+
│   └── validate.js
28+
└── views
29+
├── view_a
30+
│   └── map.js
31+
├── view_b
32+
│   └── map.js
33+
└── view_c
34+
└── map.js
35+
36+
Becomes this object::
37+
38+
{
39+
"views": {
40+
"view_a": {
41+
"map": "function(doc) { ... }"
42+
},
43+
"view_b": {
44+
"map": "function(doc) { ... }"
45+
},
46+
"view_c": {
47+
"map": "function(doc) { ... }"
48+
}
49+
},
50+
"_id": "_design/name_of_design_document",
51+
"filters": {
52+
"forms_only": "function(doc, req) { ... }"
53+
},
54+
"language": "javascript",
55+
"lib": {
56+
"validate": "// A library for validations ..."
57+
}
58+
}
59+
60+
"""
61+
62+
from __future__ import unicode_literals, absolute_import
63+
64+
import os.path
65+
import pprint
66+
import codecs
67+
import json
68+
69+
def load_design_doc(directory, strip_files=False):
70+
"""
71+
Load a design document from the filesystem.
72+
73+
strip_files: remove leading and trailing whitespace from file contents,
74+
like couchdbkit.
75+
"""
76+
objects = {}
77+
78+
for (dirpath, dirnames, filenames) in os.walk(directory, topdown=False):
79+
key = os.path.split(dirpath)[-1]
80+
ob = {}
81+
objects[dirpath] = (key, ob)
82+
83+
for name in filenames:
84+
fkey = os.path.splitext(name)[0]
85+
fullname = os.path.join(dirpath, name)
86+
with codecs.open(fullname, 'r', 'utf-8') as f:
87+
contents = f.read()
88+
if name.endswith('.json'):
89+
contents = json.loads(contents)
90+
elif strip_files:
91+
contents = contents.strip()
92+
ob[fkey] = contents
93+
94+
for name in dirnames:
95+
if name == '_attachments':
96+
raise NotImplementedError()
97+
subkey, subthing = objects[os.path.join(dirpath, name)]
98+
ob[subkey] = subthing
99+
100+
return ob
101+
102+
103+
def main():
104+
import sys
105+
try:
106+
directory = sys.argv[1]
107+
except IndexError:
108+
sys.stderr.write("Usage:\n\t{} [directory]\n".format(sys.argv[0]))
109+
sys.exit(1)
110+
obj = load_design_doc(directory)
111+
sys.stdout.write(json.dumps(obj, indent=2))
112+
113+
114+
if __name__ == "__main__":
115+
main()

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
'couchdb-dump = couchdb.tools.dump:main',
2929
'couchdb-load = couchdb.tools.load:main',
3030
'couchdb-replicate = couchdb.tools.replicate:main',
31+
'couchdb-load-design-doc = couchdb.loader:main',
3132
],
3233
},
3334
'install_requires': [],

0 commit comments

Comments
 (0)