Example #1
0
def init(conf, *args, **opts):
    if not args:
        dest = os.getcwd()
    else:
        dest = os.path.normpath(os.path.join(os.getcwd(), args[0]))

    if dest is None:
        raise AppError('Unknown dest')

    if opts['empty'] and opts['template']:
        raise AppError('option "empty" cannot use with "template"')

    if util.iscouchapp(dest):
        raise AppError("can't create an app at '{0}'. "
                       "One already exists here.".format(dest))

    if util.findcouchapp(dest):
        raise AppError("can't create an app inside another app '{0}'.".format(
            util.findcouchapp(dest)))

    # ``couchapp init -e dest``
    if opts['empty']:
        document(dest, create=True)

    # ``couchapp init -t template_name dest``
    elif opts['template']:
        generator.init_template(dest, template=opts['template'])

    # ``couchapp init dest``
    else:
        generator.init_basic(dest)

    logger.info('{0} created.'.format(dest))

    return 0
Example #2
0
def generate(conf, path, *args, **opts):
    dest = path
    if len(args) < 1:
        raise AppError("Can't generate function, name or path is missing")

    if len(args) == 1:
        kind = "app"
        name = args[0]
    elif len(args) == 2:
        kind = args[0]
        name = args[1]
    elif len(args) >= 3:
        kind = args[0]
        dest = args[1]
        name = args[2]

    if dest is None:
        if kind == "app":
            dest = os.path.normpath(os.path.join(os.getcwd(), ".", name))
            opts['create'] = True
        else:
            raise AppError("You aren't in a couchapp.")

    hook(conf, dest, "pre-generate")
    generator.generate(dest, kind, name, **opts)
    hook(conf, dest, "post-generate")
    return 0
Example #3
0
def generate(path, kind, name, **opts):
    if kind not in [
            'view', 'list', 'show', 'filter', 'function', 'vendor', 'update',
            'spatial'
    ]:
        raise AppError("Can't generate {0} in your couchapp. "
                       'generator is unknown'.format(kind))

    if name is None:
        raise AppError("Can't generate {0} function, "
                       "name is missing".format(kind))

    generate_function(path, kind, name, opts.get("template"))
Example #4
0
def generate(path, kind, name, **opts):
    if kind not in ['startapp', 'app', 'view', 'list', 'show', 'filter',
            'function', 'vendor', 'update', 'spatial']:
        raise AppError(
            "Can't generate %s in your couchapp. generator is unknown" % kind)

    if kind == "app":
        generate_app(path, template=opts.get("template"), 
                create=opts.get('create', False))
    elif kind == "startapp":
        start_app(path)
    else:
        if name is None:
            raise AppError("Can't generate %s function, name is missing" % kind)
        generate_function(path, kind, name, opts.get("template"))
Example #5
0
def generate_function(path, kind, name, template=None):
    functions_path = ['functions']
    if template:
        functions_path = []
        _relpath = os.path.join(*template.split('/'))
        template_dir = find_template_dir("templates", _relpath)
    else:
        template_dir = find_template_dir("templates")
    if template_dir:
        functions = []
        if kind == "view":
            path = os.path.join(path, "%ss" % kind, name)
            if os.path.exists(path):
                raise AppError("The view %s already exists" % name)
            functions = [('map.js', 'map.js'), ('reduce.js', 'reduce.js')]
        elif kind == "function":
            functions = [('%s.js' % name, '%s.js' % name)]
        elif kind == "vendor":
            app_dir = os.path.join(path, "vendor", name)
            try:
                os.makedirs(app_dir)
            except:
                pass
            targetpath = os.path.join(*template.split('/'))
            copy_helper(path, targetpath)
            return
        elif kind == "spatial":
            path = os.path.join(path, "spatial")
            functions = [("spatial.js", "%s.js" % name)]
        else:
            path = os.path.join(path, "%ss" % kind)
            functions = [('%s.js' % kind, "%s.js" % name)]
        try:
            os.makedirs(path)
        except:
            pass

        for template, target in functions:
            target_path = os.path.join(path, target)
            root_path = [template_dir] + functions_path + [template]
            root = os.path.join(*root_path)
            try:
                shutil.copy2(root, target_path)
            except:
                logger.warning("%s not found in %s" %
                               (template, os.path.join(*root_path[:-1])))
    else:
        raise AppError("Defaults templates not found. Check your install.")
Example #6
0
    def __init__(self, uri, create=True, **client_opts):
        if uri.endswith("/"):
            uri = uri[:-1]

        self.raw_uri = uri
        if uri.startswith("desktopcouch://"):
            if not desktopcouch:
                raise AppError("Desktopcouch isn't available on this" +
                               "machine. You can't access to %s" % uri)
            uri = "http://localhost:%s/%s" % (desktopcouch.find_port(),
                                              uri[15:])
            ctx = local_files.DEFAULT_CONTEXT
            oauth_tokens = local_files.get_oauth_tokens(ctx)

            consumer = oauth.Consumer(oauth_tokens["consumer_key"],
                                      oauth_tokens["consumer_secret"])
            token = oauth.Token(oauth_tokens["token"],
                                oauth_tokens["token_secret"])

            oauth_filter = OAuthFilter("*", consumer, token)
            filters = client_opts.get("filters") or []
            filters.append(oauth_filter)
            client_opts["filters"] = filters

        self.res = CouchdbResource(uri=uri, **client_opts)
        self.server_uri, self.dbname = uri.rsplit('/', 1)

        self.uuids = Uuids(self.server_uri, **client_opts)

        if create:
            # create the db
            try:
                self.res.head()
            except ResourceNotFound:
                self.res.put()
Example #7
0
def autopush(conf, path, *args, **opts):
    doc_path = None
    dest = None
    if len(args) < 2:
        doc_path = path
        if args:
            dest = args[0]
    else:
        doc_path = os.path.normpath(os.path.join(os.getcwd(), args[0]))
        dest = args[1]

    if doc_path is None:
        raise AppError("You aren't in a couchapp.")

    conf.update(doc_path)
    doc = document(doc_path, create=False, docid=opts.get('docid'))
    dbs = conf.get_dbs(dest)

    update_delay = int(opts.get('update_delay', DEFAULT_UPDATE_DELAY))
    noatomic = opts.get('no_atomic', False)

    watcher = CouchappWatcher(doc,
                              dbs,
                              update_delay=update_delay,
                              noatomic=noatomic)
    watcher.run()
Example #8
0
def copy_helper(path, directory, tname="templates"):
    """ copy helper used to generate an app"""
    if tname == "vendor":
        tname = os.path.join("templates", tname)

    templatedir = find_template_dir(tname, directory)
    if templatedir:
        if directory == "vendor":
            path = os.path.join(path, directory)
            try:
                os.makedirs(path)
            except:
                pass

        for root, dirs, files in os.walk(templatedir):
            rel = relpath(root, templatedir)
            if rel == ".":
                rel = ""
            target_path = os.path.join(path, rel)
            for d in dirs:
                try:
                    os.makedirs(os.path.join(target_path, d))
                except:
                    continue
            for f in files:
                shutil.copy2(os.path.join(root, f),
                             os.path.join(target_path, f))
    else:
        raise AppError(
            "Can't create a CouchApp in %s: default template not found." %
            (path))
Example #9
0
    def setup(self):
        self.noatomic = self.opts.get('no_atomic', False)
        self.update_delay = self.opts.get('update_delay', 60)
        dest = None
        doc_path = None
        if len(self.args) < 2:
            doc_path = self.path
            if self.args:
                dest = self.args[0]
        else:
            doc_path = os.path.normpath(os.path.join(os.getcwd(),
                                                     self.args[0]))
            dest = self.args[1]

        if doc_path is None:
            raise AppError("You aren't in a couchapp.")

        self.conf.update(doc_path)

        self.doc_path = doc_path
        self.doc = document(doc_path,
                            create=False,
                            docid=self.opts.get('docid'))

        self.dbs = self.conf.get_dbs(dest)

        ignorefile = os.path.join(self.doc_path, '.couchappignore')
        if os.path.exists(ignorefile):
            # A .couchappignore file is a json file containing a
            # list of regexps for things to skip
            self.ignores = json.load(open(ignorefile, 'r'))
Example #10
0
def start_app(path):
    try:
        os.makedirs(path)
    except OSError, e:
        errno, message = e
        raise AppError("Can't create a CouchApp in %s: %s" % (
                path, message))
Example #11
0
def setup_dir(path, require_empty=True):
    '''
    If dir exists, check it empty or not.
    If dir does not exist, make one.
    '''
    isdir = os.path.isdir(path)

    if isdir and not require_empty:
        return
    elif isdir and require_empty and is_empty_dir(path):
        return
    elif isdir and require_empty and not is_empty_dir(path):
        raise AppError("dir '{0}' is not empty".format(path))
    elif os.path.exists(path) and not isdir:
        raise AppError("'{0}': File exists".format(path))

    os.mkdir(path)
Example #12
0
def startapp(conf, *args, **opts):
    if len(args) < 1:
        raise AppError("Can't start an app, name or path is missing")

    if len(args) == 1:
        name = args[0]
        dest = os.path.normpath(os.path.join(os.getcwd(), ".", name))
    elif len(args) == 2:

        name = args[1]
        dest = os.path.normpath(os.path.join(args[0], args[1]))

    if os.path.isfile(os.path.join(dest, ".couchapprc")):
        raise AppError("can't create an app at '%s'. One already exists"
                       "here" % dest)

    generator.generate(dest, "startapp", name, **opts)
    return 0
Example #13
0
def generate(path, kind, name, **opts):
    kinds = ('view', 'list', 'show', 'filter', 'function', 'vendor', 'update',
             'spatial')
    if kind not in kinds:
        raise AppError("Can't generate '{0}' in your couchapp. "
                       'generator is unknown.'.format(kind))

    if kind == 'vendor':
        return generate_vendor(path, name, opts.get('template', 'default'))
    generate_function(path, kind, name, opts.get('template', 'default'))
Example #14
0
def generate(conf, path, *args, **opts):
    '''
    :param path: result of util.findcouchapp
    '''
    dest = path
    if len(args) < 1:
        raise AppError("Can't generate function, name or path is missing")

    if len(args) == 1:
        kind = "app"
        name = args[0]
    elif len(args) == 2:
        kind = args[0]
        name = args[1]
    elif len(args) >= 3:
        kind = args[0]
        dest = args[1]
        name = args[2]

    if kind == 'app':  # deprecated warning
        logger.warning('"genrate app" will be deprecated in future release. '
                       'Please use "init -t TEMPLATE" instead.')
        args = (dest, ) if dest is not None else tuple()
        kwargs = {
            'template': opts['template'] if opts['template'] else 'default',
            'empty': False
        }
        return init(conf, *args, **kwargs)

    if dest is None:
        raise AppError("You aren't in a couchapp.")

    hook(conf, dest, "pre-generate")
    generator.generate(dest, kind, name, **opts)
    hook(conf, dest, "post-generate")
    return 0
Example #15
0
    def __init__(self, source, dest=None, rev=None):
        self.source = source
        self.dest = dest
        self.rev = rev

        # init self.docid & self.dburl
        try:
            self.dburl, self.docid = self.source.split('_design/')
        except ValueError:
            raise AppError("{0} isn't a valid source".format(self.source))

        if not self.dest:
            self.dest = self.docid

        # init self.path
        self.init_path()

        # init self.db related vars here
        # affected:
        #    - self.docid
        #    - self.doc
        self.init_db()

        # init metadata
        self.init_metadata()

        # create files from manifest
        self.setup_manifest()

        # second pass for missing key or in case
        # manifest isn't in app
        self.setup_missing()

        # create couchapp.json
        self.setup_couchapp_json()

        # save id
        self.setup_id()

        # setup .couchapprc
        self.setup_couchapprc()

        # process attachments
        self.setup_attachments()

        logger.info("{src} cloned in {dest}".format(src=self.source,
                                                    dest=self.dest))
Example #16
0
    def browse_url(self, url):
        if url.startswith("desktopcouch://"):
            if not desktopcouch:
                raise AppError("Desktopcouch isn't available on this"+
                    "machine. You can't access to %s" % url)
            ctx = local_files.DEFAULT_CONTEXT
            bookmark_file = os.path.join(ctx.db_dir, "couchdb.html")
            try:
                username, password = re.findall("<!-- !!([^!]+)!!([^!]+)!! -->", 
                        open(bookmark_file).read())[-1]
            except ValueError:
                raise IOError("Bookmark file is corrupt."+
                        "Username/password are missing.")

            url = "http://%s:%s@localhost:%s/%s" % (username, password,
                desktopcouch.find_port(), url[15:])
        webbrowser.open_new_tab(url)
Example #17
0
def generate_app(path, template=None, create=False):
    """ Generates a CouchApp in app_dir 
    
    :attr verbose: boolean, default False
    :return: boolean, dict. { 'ok': True } if ok, { 'ok': False, 'error': message } 
    if something was wrong.
    """

    TEMPLATES = ['app']
    prefix = ''
    if template is not None:
        prefix = os.path.join(*template.split('/'))
    try:
        os.makedirs(path)
    except OSError, e:
        errno, message = e
        raise AppError("Can't create a CouchApp in %s: %s" % (path, message))
Example #18
0
def browse(conf, path, *args, **opts):
    if len(args) == 0:
        dest = path
        doc_path = '.'
    else:
        doc_path = path
        dest = args[0]

    doc_path = os.path.normpath(os.path.join(os.getcwd(), doc_path))
    if not util.iscouchapp(doc_path):
        raise AppError("Dir '{0}' is not a couchapp.".format(doc_path))

    conf.update(doc_path)

    doc = document(doc_path, create=False, docid=opts.get('docid'))

    dbs = conf.get_dbs(dest)
    doc.browse(dbs)
Example #19
0
def push(conf, path, *args, **opts):
    export = opts.get('export', False)
    noatomic = opts.get('no_atomic', False)
    browse = opts.get('browse', False)
    force = opts.get('force', False)
    dest = None
    doc_path = None
    if len(args) < 2:
        if export:
            if path is None and args:
                doc_path = args[0]
            else:
                doc_path = path
        else:
            doc_path = path
            if args:
                dest = args[0]
    else:
        doc_path = os.path.normpath(os.path.join(os.getcwd(), args[0]))
        dest = args[1]
    if doc_path is None:
        raise AppError("You aren't in a couchapp.")

    conf.update(doc_path)

    doc = document(doc_path, create=False, docid=opts.get('docid'))
    if export:
        if opts.get('output'):
            util.write_json(opts.get('output'), doc)
        else:
            print(doc.to_json())
        return 0

    dbs = conf.get_dbs(dest)

    hook(conf, doc_path, "pre-push", dbs=dbs)
    doc.push(dbs, noatomic, browse, force)
    hook(conf, doc_path, "post-push", dbs=dbs)

    docspath = os.path.join(doc_path, '_docs')
    if os.path.exists(docspath):
        pushdocs(conf, docspath, dest, *args, **opts)
    return 0
Example #20
0
from couchapp.errors import AppError
from couchapp.localdoc import document
from couchapp.util import json

try:
    import pyinotify
except ImportError:
    pyinotify = None

try:
    import eventlet
    eventlet.monkey_patch(os=False)
except ImportError:
    raise AppError("""Eventlet isn't installed.

Install it with the command:
        
    pip install eventlet
""")

log = logging.getLogger(__name__)


def close_on_exec(fd):
    flags = fcntl.fcntl(fd, fcntl.F_GETFD)
    flags |= fcntl.FD_CLOEXEC
    fcntl.fcntl(fd, fcntl.F_SETFD, flags)


def set_non_blocking(fd):
    flags = fcntl.fcntl(fd, fcntl.F_GETFL) | os.O_NONBLOCK
    fcntl.fcntl(fd, fcntl.F_SETFL, flags)
Example #21
0
def generate_function(path, func_type, name, template='default'):
    '''
    Generate function from template

    :param path: the app dir
    :param func_type: function type. e.g. ``view``, ``show``.
    :param name: the function name
    :param template: the template set

    The big picture of template dir is discribed
    in :py:func:`~couchapp.generate.init_template`.

    Here we show the detail structure of ``functions`` dir::

        functions/
            filter.js
            list.js
            map.js
            reduce.js
            show.js
            spatial.js
            update.js
            validate_doc_update.js
            ...
            myfunc.js
    '''
    tmpl_name = os.path.join(*template.split('/'))
    tmpl_dir = find_template_dir(tmpl_name, tmpl_type='functions',
                                 raise_error=True)

    file_list = []  # [(src, dest), ...]
    empty_dir = False
    if func_type == 'view':
        dir_ = os.path.join(path, 'views', name)
        empty_dir = True
        file_list.append(('map.js', 'map.js'))
        file_list.append(('reduce.js', 'reduce.js'))

    elif func_type in ('filter', 'list', 'show', 'update'):
        dir_ = os.path.join(path, '{0}s'.format(func_type))
        file_list.append(('{0}.js'.format(func_type),
                          '{0}.js'.format(name)))

    elif func_type == 'function':  # user defined function
        dir_ = path
        file_list.append(('{0}.js'.format(name),
                          '{0}.js'.format(name)))

    elif func_type == 'spatial':
        dir_ = os.path.join(path, 'spatial')
        file_list.append(('spatial.js', '{0}.js'.format(name)))

    elif func_type == 'validate_doc_update':
        dir_ = path
        file_list.append(('validate_doc_update.js', 'validate_doc_update.js'))

    else:
        raise AppError('unrecognized function type "{0}"'.format(func_type))

    setup_dir(dir_, require_empty=empty_dir)

    for src, dest in file_list:
        full_src = os.path.join(tmpl_dir, src)
        full_dest = os.path.join(dir_, dest)

        try:
            copy2(full_src, full_dest)
        except Error:
            logger.warning('function "%s" not found in "%s"', src, tmpl_dir)
        else:
            logger.debug('function "%s" generated successfully', dest)

    logger.info('enjoy the %s function, "%s"!', func_type, name)
Example #22
0
def clone(source, dest=None, rev=None):
    """
    Clone an application from a design_doc given.

    :attr design_doc: dict, the design doc retrieved from couchdb
    if something was wrong.
    """

    try:
        dburl, docid = source.split('_design/')
    except ValueError:
        raise AppError("%s isn't a valid source" % source)

    if not dest:
        dest = docid

    path = os.path.normpath(os.path.join(os.getcwd(), dest))
    if not os.path.exists(path):
        os.makedirs(path)

    db = client.Database(dburl[:-1], create=False)
    if not rev:
        doc = db.open_doc("_design/%s" % docid)
    else:
        doc = db.open_doc("_design/%s" % 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 = util.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(util.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 = util.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)

                    util.write(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')
                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):
                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)
                    util.write(filename, func)
                    logger.warning("clone view not in manifest: %s" % filename)
        elif key in ('shows', 'lists', 'filter', 'updates'):
            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)
                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:
                logger.warning("clone property not in manifest: %s" % key)
                if isinstance(doc[key], (
                        list,
                        tuple,
                )):
                    util.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:])
                            util.write(fieldpath, value)
                        else:
                            util.write_json(fieldpath + '.json', value)
                else:
                    value = doc[key]
                    if not isinstance(value, basestring):
                        value = str(value)
                    util.write(filedir, value)

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

    util.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 = 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)
            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) != util.sign(filepath):
                resp = db.fetch_attachment(docid, filename)
                with open(filepath, 'wb') as f:
                    for chunk in resp.body_stream():
                        f.write(chunk)
                logger.debug("clone attachment: %s" % filename)

    logger.info("%s cloned in %s" % (source, dest))
Example #23
0
def find_template_dir(tmpl_name='default', tmpl_type='', raise_error=False):
    '''
    Find template dir for different platform

    :param tmpl_name: The template name under ``templates``.
                      It can be empty string.
                      If it is set to ``default``, we will use consider
                      the tmpl_name as empty.
                      e.g. ``mytmpl`` mentioned in the docstring of
                      :py:func:`~couchapp.generate.init_template`
    :param tmpl_type: the type of template.
                      e.g. 'app', 'functions', 'vendor'
    :param bool raise_error: raise ``AppError`` if not found
    :return: the absolute path or ``None`` if not found

    We will check the ``<search path>/templates/<tmpl_name>/<tmpl_type>`` is
    dir or not. The first matched win.

    For posix platform, the search locations are following:
    - ~/.couchapp/
    - <module dir path>/
    - <module dir path>/../
    - /usr/share/couchapp/
    - /usr/local/share/couchapp/
    - /opt/couchapp/

    For darwin (OSX) platform, we have some extra search locations:
    - ${HOME}/Library/Application Support/Couchapp/

    For windows with standlone binary (py2exe):
    - <executable dir path>/
    - <executable dir path>/../

    For windows with python interpreter:
    - ${USERPROFILE}/.couchapp/
    - <module dir path>/
    - <module dir path>/../
    - <python prefix>/Lib/site-packages/couchapp/

    ..versionchanged:: 1.1
    '''
    if tmpl_type and tmpl_type not in TEMPLATE_TYPES:
        raise AppError('invalid template type "{0}"'.format(tmpl_type))

    if tmpl_name == 'default':
        tmpl_name = ''

    modpath = os.path.dirname(__file__)
    search_paths = user_path() + [
        modpath,
        os.path.join(modpath, '..'),
    ]

    if os.name == 'posix':
        search_paths.extend([
            '/usr/share/couchapp',
            '/usr/local/share/couchapp',
            '/opt/couchapp',
        ])
    elif is_py2exe():
        search_paths.append(os.path.dirname(sys.executable))
    elif is_windows():
        search_paths.append(
            os.path.join(sys.prefix, 'Lib', 'site-packages', 'couchapp')
        )

    # extra path for darwin
    if sys.platform.startswith('darwin'):
        search_paths.append(
            os.path.expanduser('~/Library/Application Support/Couchapp')
        )

    # the first win!
    for path in search_paths:
        path = os.path.normpath(path)
        path = os.path.join(path, 'templates', tmpl_name, tmpl_type)
        if os.path.isdir(path):
            logger.debug('template path match: "{0}"'.format(path))
            return path

        logger.debug('template search path: "{0}" not found'.format(path))

    if raise_error:
        logger.info('please use "-d" to checkout search paths.')
        raise AppError('template "{0}/{1}" not found.'.format(
            tmpl_name, tmpl_type))

    return None
Example #24
0
def init_template(path, template='default'):
    '''
    Generates a CouchApp via template

    :param str path: the app dir
    :param str template: the templates set name. In following example, it is
                         ``mytmpl``.

    We expect template dir has following structure::

        templates/
            app/
            functions/
            vendor/

            mytmpl/
                app/
                functions/
                vendor/

            vuejs/
                myvue/
                    app/
                    functions/
                    vendor/
                vueform/
                    app/
                    functions/
                    vendor/

    The ``templates/app`` will be used as default app template.
    ``templates/functions`` and ``templates/vender`` are default, also.

    And we can create a dir ``mytmpl`` as custom template set.
    The template set name can be nested, e.g. ``vuejs/myvue``.

    ..versionadded:: 1.1
    '''
    if template in TEMPLATE_TYPES:
        raise AppError('template name connot be {0}.'.format(TEMPLATE_TYPES))

    tmpl_name = os.path.normpath(template) if template else ''

    # copy ``<template set>/app``
    src_dir = find_template_dir(tmpl_name, 'app', raise_error=True)
    copy_helper(src_dir, path)

    # construct basic dirs
    setup_dirs((os.path.join(path, n) for n in DEFAULT_APP_TREE),
               require_empty=False)

    # add vendor
    src_dir = find_template_dir(tmpl_name, tmpl_type='vendor')
    if src_dir is None:
        logger.debug('vendor not found in template set "{0}". '
                     'fallback to default vendor.'.format(tmpl_name))
        src_dir = find_template_dir(tmpl_type='vendor')
    vendor_dir = os.path.join(path, 'vendor')
    copy_helper(src_dir, vendor_dir)

    save_id(path, '_design/{0}'.format(os.path.split(path)[-1]))
    localdoc.document(path, create=True)
Example #25
0
def test_dispatch_AppError(_dispatch, logger):
    args = ['strange']
    _dispatch.side_effect = AppError('some error')

    assert dispatch.dispatch(args) == -1
    _dispatch.assert_called_with(args)