Skip to content

Commit

Permalink
refactor the code to make it easy. no more specific
Browse files Browse the repository at this point in the history
extensions/hooks/vendors parsing. Now you can use entry points to
publish your own couchapp extensions/vendors/hooks. Hooks can also be simple script. While
i'm here remove ui object and just use a config object.

Edit the setup.py which is now more portable too.
  • Loading branch information
benoitc committed Mar 22, 2010
1 parent 4135711 commit 7ee27cb
Show file tree
Hide file tree
Showing 30 changed files with 799 additions and 989 deletions.
11 changes: 5 additions & 6 deletions couchapp/client.py
Expand Up @@ -6,13 +6,13 @@
from __future__ import with_statement
import base64
import itertools
import mimetypes
import re
import tempfile
import types

from couchapp import __version__
from couchapp.errors import ResourceNotFound, ResourceConflict,\
PreconditionFailed, RequestFailed, BulkSaveError
PreconditionFailed, RequestFailed, BulkSaveError, Unauthorized, \
InvalidAttachment
from couchapp.restkit import Resource, HttpResponse, ResourceError, request
from couchapp.restkit import util
import couchapp.simplejson as json
Expand Down Expand Up @@ -157,9 +157,8 @@ class Database(CouchdbResource):
A Database object can act as a Dict object.
"""

def __init__(self, ui, uri, create=True, **client_opts):
def __init__(self, uri, **client_opts):
CouchdbResource.__init__(self, uri=uri, **client_opts)
self.ui = ui
self.server_uri, self.dbname = uri.rsplit('/', 1)

self.uuids = Uuids(self.server_uri)
Expand Down Expand Up @@ -323,7 +322,7 @@ def is_id(doc):
errors = []
for i, r in enumerate(json_res):
if 'error' in r:
doc1 = docs[u]
doc1 = docs[i]
doc1.update({'_id': r['id'],
'_rev': r['rev']})
errors.append(doc1)
Expand Down
84 changes: 25 additions & 59 deletions couchapp/app.py → couchapp/clone_app.py
Expand Up @@ -8,6 +8,7 @@
import base64
import copy
from hashlib import md5
import logging
import os
import os.path
try:
Expand All @@ -17,15 +18,10 @@

from couchapp.errors import AppError
from couchapp import client
from couchapp.utils import to_bytestring
import couchapp.generator as generator
from couchapp.vendor import Vendor
import couchapp.localdoc as localdoc
from couchapp import util

logger = logging.getLogger(__name__)

def document(ui, path='', create=False, docid=None):
doc = localdoc.instance(ui, path, create=create, docid=docid)
return doc

if os.name == 'nt':
def _replace_slash(name):
Expand All @@ -34,7 +30,7 @@ def _replace_slash(name):
def _replace_slash(name):
return name

def clone(ui, source, dest=None, rev=None):
def clone(source, dest=None, rev=None):
"""
Clone an application from a design_doc given.
Expand All @@ -54,7 +50,7 @@ def clone(ui, source, dest=None, rev=None):
if not os.path.exists(path):
os.makedirs(path)

db = client.Database(ui, dburl[:-1])
db = client.Database(dburl[:-1])
if not rev:
doc = db.open_doc("_design/%s" % docid)
else:
Expand All @@ -76,16 +72,15 @@ def clone(ui, source, dest=None, rev=None):
# create files from manifest
if manifest:
for filename in manifest:
if ui.verbose >=2:
ui.logger.info("clone property: %s" % filename)
logger.info("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 = ui.split_path(filename)
parts = util.split_path(filename)
fname = parts.pop()
v = doc
while 1:
Expand All @@ -105,7 +100,7 @@ def clone(ui, source, dest=None, rev=None):


if isinstance(content, basestring):
_ref = md5(to_bytestring(content)).hexdigest()
_ref = md5(util.to_bytestring(content)).hexdigest()
if objects and _ref in objects:
content = objects[_ref]

Expand All @@ -122,7 +117,7 @@ def clone(ui, source, dest=None, rev=None):
if not os.path.isdir(filedir):
os.makedirs(filedir)

ui.write(filepath, content)
util.write(filepath, content)

# remove the key from design doc
temp = doc
Expand Down Expand Up @@ -151,7 +146,7 @@ def clone(ui, source, dest=None, rev=None):
del app_meta['length']
if app_meta:
couchapp_file = os.path.join(path, 'couchapp.json')
ui.write_json(couchapp_file, app_meta)
util.write_json(couchapp_file, app_meta)
elif key in ('views'):
vs_dir = os.path.join(path, key)
if not os.path.isdir(vs_dir):
Expand All @@ -163,30 +158,26 @@ def clone(ui, source, dest=None, rev=None):
for func_name, func in vs_item.iteritems():
filename = os.path.join(vs_item_dir, '%s.js' %
func_name)
ui.write(filename, func)
if ui.verbose >=2:
ui.logger.info(
"clone view not in manifest: %s" % filename)
util.write(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)
ui.write(filename, func)
if ui.verbose >=2:
ui.logger.info(
"clone show or list not in manifest: %s" % filename)
util.write(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:
if ui.verbose >=2:
ui.logger.info("clone property not in manifest: %s" % key)
logger.warning("clone property not in manifest: %s" % key)
if isinstance(doc[key], (list, tuple,)):
ui.write_json(filedir + ".json", doc[key])
util.write_json(filedir + ".json", doc[key])
elif isinstance(doc[key], dict):
if not os.path.isdir(filedir):
os.makedirs(filedir)
Expand All @@ -195,20 +186,20 @@ def clone(ui, source, dest=None, rev=None):
if isinstance(value, basestring):
if value.startswith('base64-encoded;'):
value = base64.b64decode(content[15:])
ui.write(fieldpath, value)
util.write(fieldpath, value)
else:
ui.write_json(fieldpath + '.json', value)
util.write_json(fieldpath + '.json', value)
else:
value = doc[key]
if not isinstance(value, basestring):
value = str(value)
ui.write(filedir, value)
util.write(filedir, value)

# save id
idfile = os.path.join(path, '_id')
ui.write(idfile, doc['_id'])
util.write(idfile, doc['_id'])

ui.write_json(os.path.join(path, '.couchapprc'), {})
util.write_json(os.path.join(path, '.couchapprc'), {})

if '_attachments' in doc: # process attachments
attachdir = os.path.join(path, '_attachments')
Expand All @@ -217,7 +208,7 @@ def clone(ui, source, dest=None, rev=None):

for filename in doc['_attachments'].iterkeys():
if filename.startswith('vendor'):
attach_parts = ui.split_path(filename)
attach_parts = util.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)
Expand All @@ -228,34 +219,9 @@ def clone(ui, source, dest=None, rev=None):
if not os.path.isdir(currentdir):
os.makedirs(currentdir)

if signatures.get(filename) != ui.sign(filepath):
if signatures.get(filename) != util.sign(filepath):
resp = db.fetch_attachment(docid, filename)
with open(filepath, 'wb') as f:
for chunk in resp.body_file:
f.write(chunk)
if ui.verbose>=2:
ui.logger.info("clone attachment: %s" % filename)

def generate(ui, path, kind, name, **opts):
if kind not in ["app", "view", "list", "show", 'filter', 'function',
'vendor', 'update']:
raise AppError(
"Can't generate %s in your couchapp. generator is unknown" % kind)

if kind == "app":
generator.generate_app(ui, path, template=opts.get("template"),
create=opts.get('create', False))
else:
if name is None:
raise AppError("Can't generate %s function, name is missing" % kind)
generator.generate_function(ui, path, kind, name, opts.get("template"))


def vendor_install(ui, dest, source, *args, **opts):
vendor = Vendor(ui)
vendor.install(dest, source, *args, **opts)

def vendor_update(ui, dest, name=None, *args, **opts):
vendor = Vendor(ui)
vendor.update(dest, name, *args, **opts)

logger.info("clone attachment: %s" % filename)

0 comments on commit 7ee27cb

Please sign in to comment.