def apply_lib(doc, funcs, app_dir, objs): for k, v in funcs.items(): if not isinstance(v, basestring): continue else: logger.debug("process function: %s" % k) old_v = v try: funcs[k] = run_json_macros(doc, run_code_macros(v, app_dir), app_dir) except ValueError, e: raise MacroError( "Error running !code or !json on function \"%s\": %s" % (k, e)) if old_v != funcs[k]: objs[md5(to_bytestring(funcs[k])).hexdigest()] = old_v
def apply_lib(doc, funcs, app_dir, objs, verbose=False): """ run code macros and json macros on a list of funcs. It also maintain a list of processed code to be sure to not processing twice """ for k, v in funcs.iteritems(): if isinstance(v, basestring): old_v = v try: funcs[k] = run_json_macros(doc, run_code_macros(v, app_dir, verbose=verbose), app_dir, verbose=verbose) except ValueError, e: print >>sys.stderr, "Error running !code or !json on function \"%s\": %s" % (k, e) sys.exit(-1) if old_v != funcs[k]: objs[md5(to_bytestring(funcs[k])).hexdigest()] = old_v
def apply_lib(doc, funcs, app_dir, objs, verbose=False): """ run code macros and json macros on a list of funcs. It also maintain a list of processed code to be sure to not processing twice """ for k, v in funcs.iteritems(): if isinstance(v, basestring): old_v = v try: funcs[k] = run_json_macros(doc, run_code_macros(v, app_dir, verbose=verbose), app_dir, verbose=verbose) except ValueError, e: print >> sys.stderr, "Error running !code or !json on function \"%s\": %s" % ( k, e) sys.exit(-1) if old_v != funcs[k]: objs[md5(to_bytestring(funcs[k])).hexdigest()] = old_v
def clone(db, docid, dest=None, rev=None): """ Clone a CouchDB document to the fs. """ if not dest: dest = docid path = os.path.normpath(os.path.join(os.getcwd(), dest)) if not os.path.exists(path): os.makedirs(path) if not rev: doc = db.open_doc(docid) else: doc = db.open_doc(docid, rev=rev) docid = doc['_id'] metadata = doc.get('couchapp', {}) # get manifest manifest = metadata.get('manifest', {}) # get signatures signatures = metadata.get('signatures', {}) # get objects refs objects = metadata.get('objects', {}) # create files from manifest if manifest: for filename in manifest: logger.debug("clone property: %s" % filename) filepath = os.path.join(path, filename) if filename.endswith('/'): if not os.path.isdir(filepath): os.makedirs(filepath) elif filename == "couchapp.json": continue else: parts = utils.split_path(filename) fname = parts.pop() v = doc while 1: try: for key in parts: v = v[key] except KeyError: break # remove extension last_key, ext = os.path.splitext(fname) # make sure key exist try: content = v[last_key] except KeyError: break if isinstance(content, basestring): _ref = md5(utils.to_bytestring(content)).hexdigest() if objects and _ref in objects: content = objects[_ref] if content.startswith('base64-encoded;'): content = base64.b64decode(content[15:]) if fname.endswith('.json'): content = utils.json.dumps(content).encode('utf-8') del v[last_key] # make sure file dir have been created filedir = os.path.dirname(filepath) if not os.path.isdir(filedir): os.makedirs(filedir) utils.write_content(filepath, content) # remove the key from design doc temp = doc for key2 in parts: if key2 == key: if not temp[key2]: del temp[key2] break temp = temp[key2] # second pass for missing key or in case # manifest isn't in app for key in doc.iterkeys(): if key.startswith('_'): continue elif key in ('couchapp'): app_meta = copy.deepcopy(doc['couchapp']) if 'signatures' in app_meta: del app_meta['signatures'] if 'manifest' in app_meta: del app_meta['manifest'] if 'objects' in app_meta: del app_meta['objects'] if 'length' in app_meta: del app_meta['length'] if app_meta: couchapp_file = os.path.join(path, 'couchapp.json') utils.write_json(couchapp_file, app_meta) elif key in ('views'): vs_dir = os.path.join(path, key) if not os.path.isdir(vs_dir): os.makedirs(vs_dir) for vsname, vs_item in doc[key].iteritems(): vs_item_dir = os.path.join(vs_dir, vsname) if not os.path.isdir(vs_item_dir): os.makedirs(vs_item_dir) for func_name, func in vs_item.iteritems(): filename = os.path.join(vs_item_dir, '%s.js' % func_name) utils.write_content(filename, func) logger.warning("clone view not in manifest: %s" % filename) elif key in ('shows', 'lists', 'filter', 'update'): showpath = os.path.join(path, key) if not os.path.isdir(showpath): os.makedirs(showpath) for func_name, func in doc[key].iteritems(): filename = os.path.join(showpath, '%s.js' % func_name) utils.write_content(filename, func) logger.warning( "clone show or list not in manifest: %s" % filename) else: filedir = os.path.join(path, key) if os.path.exists(filedir): continue else: logger.warning("clone property not in manifest: %s" % key) if isinstance(doc[key], (list, tuple,)): utils.write_json(filedir + ".json", doc[key]) elif isinstance(doc[key], dict): if not os.path.isdir(filedir): os.makedirs(filedir) for field, value in doc[key].iteritems(): fieldpath = os.path.join(filedir, field) if isinstance(value, basestring): if value.startswith('base64-encoded;'): value = base64.b64decode(content[15:]) utils.write_content(fieldpath, value) else: utils.write_json(fieldpath + '.json', value) else: value = doc[key] if not isinstance(value, basestring): value = str(value) utils.write_content(filedir, value) # save id idfile = os.path.join(path, '_id') utils.write_content(idfile, doc['_id']) utils.write_json(os.path.join(path, '.couchapprc'), {}) if '_attachments' in doc: # process attachments attachdir = os.path.join(path, '_attachments') if not os.path.isdir(attachdir): os.makedirs(attachdir) for filename in doc['_attachments'].iterkeys(): if filename.startswith('vendor'): attach_parts = utils.split_path(filename) vendor_attachdir = os.path.join(path, attach_parts.pop(0), attach_parts.pop(0), '_attachments') filepath = os.path.join(vendor_attachdir, *attach_parts) else: filepath = os.path.join(attachdir, filename) filepath = _replace_slash(filepath) currentdir = os.path.dirname(filepath) if not os.path.isdir(currentdir): os.makedirs(currentdir) if signatures.get(filename) != utils.sign_file(filepath): resp = db.fetch_attachment(docid, filename, stream=True) with open(filepath, 'wb') as f: for chunk in resp.body_stream(): f.write(chunk) logger.debug("clone attachment: %s" % filename) logger.debug("%s/%s cloned in %s" % (db.uri, docid, dest))