/usr/share/pyshared/couchdbkit/designer/macros.py is in python-couchdbkit 0.6.5-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | # -*- coding: utf-8 -*-
#
# This file is part of couchdbkit released under the MIT license.
# See the NOTICE for more information.
"""
Macros used by loaders. compatible with couchapp. It allow you to include code,
design docs members inside your views, shows and lists.
for example to include a code, add just after first function the line :
// !code relativepath/to/some/code.js
To include a member of design doc and use it as a simple javascript object :
// !json some.member.i.want.to.include
All in one, example of a view :
function(doc) {
!code _attachments/js/md5.js
if (doc.type == "user") {
doc.gravatar = hex_md5(user.email);
emit(doc.username, doc)
}
}
This example includes md5.js code and uses md5 function to create gravatar hash
in your views. So you could just store raw data in your docs and calculate
hash when views are updated.
"""
import glob
from hashlib import md5
import logging
import os
import re
from ..exceptions import MacroError
from ..utils import read_file, read_json, to_bytestring, json
logger = logging.getLogger(__name__)
def package_shows(doc, funcs, app_dir, objs):
apply_lib(doc, funcs, app_dir, objs)
def package_views(doc, views, app_dir, objs):
for view, funcs in views.iteritems():
if hasattr(funcs, "items"):
apply_lib(doc, funcs, app_dir, objs)
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 run_code_macros(f_string, app_dir):
def rreq(mo):
# just read the file and return it
path = os.path.join(app_dir, mo.group(2).strip())
library = ''
filenum = 0
for filename in glob.iglob(path):
logger.debug("process code macro: %s" % filename)
try:
cnt = read_file(filename)
if cnt.find("!code") >= 0:
cnt = run_code_macros(cnt, app_dir)
library += cnt
except IOError, e:
raise MacroError(str(e))
filenum += 1
if not filenum:
raise MacroError(
"Processing code: No file matching '%s'" % mo.group(2))
return library
re_code = re.compile('(\/\/|#)\ ?!code (.*)')
return re_code.sub(rreq, f_string)
def run_json_macros(doc, f_string, app_dir):
included = {}
varstrings = []
def rjson(mo):
if mo.group(2).startswith('_attachments'):
# someone want to include from attachments
path = os.path.join(app_dir, mo.group(2).strip())
filenum = 0
for filename in glob.iglob(path):
logger.debug("process json macro: %s" % filename)
library = ''
try:
if filename.endswith('.json'):
library = read_json(filename)
else:
library = read_file(filename)
except IOError, e:
raise MacroError(str(e))
filenum += 1
current_file = filename.split(app_dir)[1]
fields = current_file.split('/')
count = len(fields)
include_to = included
for i, field in enumerate(fields):
if i+1 < count:
include_to[field] = {}
include_to = include_to[field]
else:
include_to[field] = library
if not filenum:
raise MacroError(
"Processing code: No file matching '%s'" % mo.group(2))
else:
logger.debug("process json macro: %s" % mo.group(2))
fields = mo.group(2).strip().split('.')
library = doc
count = len(fields)
include_to = included
for i, field in enumerate(fields):
if not field in library:
logger.warning(
"process json macro: unknown json source: %s" % mo.group(2))
break
library = library[field]
if i+1 < count:
include_to[field] = include_to.get(field, {})
include_to = include_to[field]
else:
include_to[field] = library
return f_string
def rjson2(mo):
return '\n'.join(varstrings)
re_json = re.compile('(\/\/|#)\ ?!json (.*)')
re_json.sub(rjson, f_string)
if not included:
return f_string
for k, v in included.iteritems():
varstrings.append("var %s = %s;" % (k, json.dumps(v).encode('utf-8')))
return re_json.sub(rjson2, f_string)
|