Пример #1
0
    def test_compress_js(self):
        from couchapp.config import Config

        config = Config()
        config.conf["compress"] = {"js": {"foo": ["shows/example-show.js"]}}
        with mock.patch("couchapp.hooks.compress.default.compress", return_value="foo") as mock_compress:
            from couchapp.hooks.compress import Compress

            compress = Compress(os.path.join(os.path.dirname(__file__), "testapp"))
            compress.conf = config
            with mock.patch("couchapp.util.write"):
                compress.run()
        self.assertTrue(mock_compress.called, "Default compressor has been called")
Пример #2
0
 def test_compress_js(self):
     from couchapp.config import Config
     config = Config()
     config.conf['compress'] = {'js': {'foo': ['shows/example-show.js']}}
     with mock.patch('couchapp.hooks.compress.default.compress',
                     return_value='foo') as mock_compress:
         from couchapp.hooks.compress import Compress
         compress = Compress(
             os.path.join(os.path.dirname(__file__), 'testapp'))
         compress.conf = config
         with mock.patch('couchapp.util.write'):
             compress.run()
     self.assertTrue(mock_compress.called,
                     'Default compressor has been called')
Пример #3
0
def test_config_init_local(rcpath, getcwd, local_conf):
    '''
    Test case for Config.__init__() in a CouchApp
    '''
    config = Config()

    local_conf.assert_called_with('/mockapp')
    assert config.local_conf == {'mock': True}, config.local_conf
Пример #4
0
 def __init__(self, dbName, couchUrl=None):
     self.couchUrl = os.environ.get("COUCHURL", couchUrl)
     self.dbName = dbName
     if self.couchUrl == None:
         msg = "COUCHRURL env var not set..."
         raise RuntimeError(msg)
     if self.couchUrl.endswith('/'):
         raise RuntimeError("COUCHURL env var shouldn't end with /")
     self.couchServer = CouchServer(self.couchUrl)
     self.couchappConfig = Config()
Пример #5
0
def installCouchApp(couchUrl, couchDBName, couchAppName, basePath=None):
    """
    _installCouchApp_

    Install the given couch app on the given server in the given database.  If
    the database already exists it will be deleted.
    """
    if not basePath:
        basePath = couchAppRoot()
    print("Installing %s into %s" % (couchAppName, couchDBName))

    couchServer = CouchServer(couchUrl)
    couchappConfig = Config()

    couchapppush(couchappConfig, "%s/%s" % (basePath, couchAppName),
                 "%s/%s" % (couchUrl, couchDBName))
    return
Пример #6
0
def test_config_init(rcpath, getcwd):
    '''
    Test case for Config.__init__()

    Check following vars:
    - self.rc_path
    - self.global_conf
    - self.local_conf
    - self.app_dir
    - self.conf
    '''
    config = Config()

    assert config.rc_path == ['/mock/couchapp.conf'], config.rc_path
    assert config.global_conf == Config.DEFAULTS, config.global_conf
    assert config.local_conf == {}, config.local_conf
    assert config.app_dir is None, config.app_dir
    assert config.conf == Config.DEFAULTS
Пример #7
0
def _dispatch(args):
    conf = Config()

    # update commands
    for mod in conf.extensions:
        cmdtable = getattr(mod, 'cmdtable', {})
        commands.table.update(cmdtable)

    cmd, globalopts, opts, args = _parse(args)

    if globalopts["help"]:
        del globalopts["help"]
        return commands.usage(conf, *args, **globalopts)
    elif globalopts["version"]:
        del globalopts["version"]
        return commands.version(conf, *args, **globalopts)

    verbose = 2
    if globalopts["debug"]:
        verbose = 1
        import restkit
        restkit.set_logging("debug")
    elif globalopts["verbose"]:
        verbose = 1
    elif globalopts["quiet"]:
        verbose = 0

    set_logging_level(verbose)
    if cmd is None:
        raise CommandLineError("unknown command")

    fun = commands.table[cmd][0]
    if cmd in commands.incouchapp:
        return fun(conf, conf.app_dir, *args, **opts)

    return fun(conf, *args, **opts)
Пример #8
0
class TestConfig():
    @patch('couchapp.config.util.findcouchapp', return_value=None)
    @patch('couchapp.config.util.rcpath', return_value=['/mock/couchapp.conf'])
    def setup(self, rcpath, getcwd):
        self.config = Config()

    def teardown(self):
        del self.config

    @raises(AttributeError)
    def test_getattr(self):
        '''
        Test case for Config.__getattr__()
        '''
        assert self.config.conf == Config.DEFAULTS
        assert self.config.env == {}
        self.config.mock  # raise AttributeError

    @raises(KeyError)
    def test_getitem(self):
        '''
        Test case for Config.__getitem__()
        '''
        assert self.config['conf'] == Config.DEFAULTS
        assert self.config['env'] == {}
        assert self.config['mock']  # raise KeyError

    def test_contains(self):
        '''
        Test case for Config.__contains__()
        '''
        assert 'env' in self.config
        assert 'hooks' in self.config
        assert 'extensions' in self.config

    @patch('couchapp.config.util.read_json', return_value={'mock': True})
    @patch('couchapp.config.os.path.isfile', return_value=True)
    def test_load_from_list(self, isfile, read_json):
        '''
        Test case for Config.load(list, default)
        '''
        default = {'foo': 'bar'}

        conf = self.config.load(['/mock/couchapp.conf'], default)

        assert conf == {'foo': 'bar', 'mock': True}
        isfile.assert_called_with('/mock/couchapp.conf')
        read_json.assert_called_with('/mock/couchapp.conf',
                                     use_environment=True,
                                     raise_on_error=True)

    @patch('couchapp.config.util.read_json', return_value={'mock': True})
    @patch('couchapp.config.os.path.isfile', return_value=True)
    def test_load_from_str(self, isfile, read_json):
        '''
        Test case for Config.load(str)
        '''
        conf = self.config.load('/mock/couchapp.conf')

        assert conf == {'mock': True}
        isfile.assert_called_with('/mock/couchapp.conf')
        read_json.assert_called_with('/mock/couchapp.conf',
                                     use_environment=True,
                                     raise_on_error=True)

    @patch('couchapp.config.util.read_json', return_value={'mock': True})
    @patch('couchapp.config.os.path.isfile', return_value=False)
    def test_load_notfile(self, isfile, read_json):
        '''
        Test case for Config.load(['/not_a_file'], default)
        '''
        default = {'foo': 'bar'}

        conf = self.config.load(['/not_a_file'], default)

        assert conf == {'foo': 'bar'}
        isfile.assert_called_with('/not_a_file')
        assert not read_json.called

    @raises(AppError)
    @patch('couchapp.config.util.read_json', side_effect=ValueError)
    @patch('couchapp.config.os.path.isfile', return_value=True)
    def test_load_apperror(self, isfile, read_json):
        '''
        Test case for Config.load() reading a invalid file
        '''
        self.config.load('/mock/couchapp.conf')
        isfile.assert_called_with('/mock/couchapp.conf')

    @patch('couchapp.config.util.read_json', return_value={'mock': True})
    @patch('couchapp.config.os.path.isfile', return_value=True)
    def test_load_deepcopy_default(self, isfile, read_json):
        '''
        Test case for checking Config.load() deepcopy param ``default``
        '''
        default = {'foo': {'bar': 'fake'}}

        conf = self.config.load('/mock.conf', default=default)

        assert conf == {
            'foo': {'bar': 'fake'},
            'mock': True
            }
        assert default == {'foo': {'bar': 'fake'}}

    @patch('couchapp.config.Config.load', return_value='mock')
    def test_load_local(self, load):
        '''
        Test case for Config.load_local()
        '''
        assert self.config.load_local('/mock') == 'mock'

        paths = (load.call_args_list[0][0][0], load.call_args_list[1][0][0])
        assert paths == ('/mock/couchapp.json', '/mock/.couchapprc'), paths

    @raises(AppError)
    @patch('couchapp.config.Config.load')
    def test_load_local_apperror(self, load):
        '''
        Test case for Config.load_local() with empty `app_dir`
        '''
        self.config.load_local(None)
        assert not load.called

    @patch('couchapp.config.Config.load')
    def test_load_local_prevent_env(self, load):
        '''
        Test case for Config.load_local() with ``env`` field in ``couchapp.json``
        '''
        def load_side_effect(path, default={}):
            print(path == '/mock/couchapp.json', path)
            if path == '/mock/couchapp.json':
                default.update({'env': 'fake_env', 'name': 'MockApp'})
            elif path == '/mock/.couchapprc':
                default.update({'hook': 'mock_hook'})
            else:
                raise AssertionError('Unknown local config file "{}"'.format(
                                     path))
            return default

        load.side_effect = load_side_effect
        conf = self.config.load_local('/mock')

        assert conf['name'] == 'MockApp'
        assert conf['hook'] == 'mock_hook'
        assert conf.get('env', None) is None

    @patch('couchapp.config.Config.load_local', return_value={'mock': True})
    def test_update(self, load_local):
        '''
        Test case for Config.update()
        '''
        self.config.update('/mock')

        assert self.config.conf.get('mock') == True
        load_local.assert_called_with('/mock')

    @patch('couchapp.config.util.load_py')
    def test_extensions_empty(self, load_py):
        '''
        Test case for empty Config.extensions
        '''
        assert self.config.extensions == []
        assert not load_py.called

    @patch('couchapp.config.util.load_py', return_value='mock')
    def test_extensions_mock(self, load_py):
        '''
        Test case for Config.extensions
        '''
        self.config.conf['extensions'] = ['mock_path']
        extensions = self.config.extensions

        assert extensions == ['mock'], extensions
        load_py.assert_called_with('mock_path', self.config)

    @patch('couchapp.config.util.hook_uri')
    def test_hook_empty(self, hook_uri):
        '''
        Test case for empty Config.hooks
        '''
        assert self.config.hooks == {}
        assert not hook_uri.called

    @patch('couchapp.config.util.hook_uri', return_value='mock_module')
    def test_hook_mock(self, hook_uri):
        '''
        Test case for Config.hooks
        '''
        self.config.conf['hooks'] = {'pre-push': ['mock_path']}
        hooks = self.config.hooks

        assert hooks == {'pre-push': ['mock_module']}, hooks
        hook_uri.assert_called_with('mock_path', self.config)

    @patch('couchapp.config.Database', return_value='mockdb')
    def test_get_dbs_full_uri(self, Database):
        '''
        Test case for Config.get_dbs() with full uri
        '''
        db_string = 'https://foo.bar'

        assert self.config.get_dbs(db_string) == ['mockdb']
        Database.assert_called_with(db_string, use_proxy=False)

    @patch('couchapp.config.Database', return_value='mockdb')
    def test_get_dbs_short_uri(self, Database):
        '''
        Test case for Config.get_dbs() with short uri
        '''
        full_uri = 'http://127.0.0.1:5984/foo'

        assert self.config.get_dbs('foo') == ['mockdb']
        Database.assert_called_with(full_uri, use_proxy=False)

    @patch('couchapp.config.Database', return_value='mockdb')
    def test_get_dbs_env(self, Database):
        '''
        Test case for Config.get_dbs() with env set
        '''
        db_string = 'http://foo.bar'
        self.config.conf['env'] = {'default': {'db': db_string}}

        assert self.config.get_dbs() == ['mockdb']
        Database.assert_called_with(db_string, use_proxy=False)

    @raises(AppError)
    @patch('couchapp.config.Database')
    def test_get_dbs_empty_env(self, Database):
        '''
        Test case for Config.get_dbs() without env set
        '''
        self.config.get_dbs()
        assert not Database.called

    @patch('couchapp.config.Database', return_value='mockdb')
    def test_get_dbs_short_env(self, Database):
        '''
        Test case for Config.get_dbs() with a short name in env
        '''
        self.config.conf['env'] = {'foo': {'db': 'http://foo.bar'}}

        assert self.config.get_dbs('foo') == ['mockdb']
        Database.assert_called_with('http://foo.bar', use_proxy=False)

    @patch('couchapp.config.Database', return_value='mockdb')
    def test_get_dbs_env_fake(self, Database):
        '''
        Test case for Config.get_dbs() with an useless env

        Assume .couchapprc is (no `db` field in `foo`)
        ```
        {
            'foo':{
                'notdb': 'mock'
            }
        }
        ```

        Expect behavior: fall back to DEFAULT_SERVER_URI/foo
        '''
        self.config.conf['env'] = {'foo': {'notdb': 'mock'}}
        default_uri = 'http://127.0.0.1:5984/foo'

        assert self.config.get_dbs('foo') == ['mockdb']
        Database.assert_called_with(default_uri, use_proxy=False)


    @patch('couchapp.config.Database', return_value='mockdb')
    def test_get_dbs_proxy(self, Database):
        '''
        Test case for Config.get_dbs() with https_proxy env
        '''
        with patch.dict('couchapp.config.os.environ', {'https_proxy': 'foo'}):
            assert self.config.get_dbs('https://bar') == ['mockdb']

        Database.assert_called_with('https://bar', use_proxy=True)

    def test_get_app_name_default(self):
        '''
        Test case for Config.get_app_name() without args and env
        '''
        assert self.config.get_app_name() == None

    def test_get_app_name_default_env(self):
        '''
        Test case for Config.get_app_name() without args but env

        env: {
            'default': {
                'name': 'MockApp'
            }
        }
        and
        env: {
            'mockname': {
                'name': 'MockApp2'
            }
        }
        '''
        self.config.conf['env'] = {'default': {'name': 'MockApp'}}
        assert self.config.get_app_name() == 'MockApp'

        self.config.conf['env'] = {'mockname': {'name': 'MockApp2'}}
        assert self.config.get_app_name('mockname') == 'MockApp2'

        self.config.conf['env'] = {'default': {'name': 'MockApp3'}}
        assert self.config.get_app_name('strang') == 'MockApp3'

    def test_get_app_name_http_uri(self):
        '''
        Test case for Config.get_app_name('http://foo.bar', default)

        If the dbstring is full uri, return ``default``
        '''
        ret = self.config.get_app_name('http://foo.bar', 'mockapp')
        assert ret == 'mockapp'

    def test_iter(self):
        '''
        Test case for Config.__iter__()
        '''
        self.config.conf['env'] = {'mock': True}
        ls = list(self.config)

        assert ('env', {'mock': True}) in ls, ls
        assert ('hooks', {}) in ls, ls

    def test_get(self):
        '''
        Test case for Config.get('__init__')
        '''
        assert callable(self.config.get('__init__'))

    def test_get_default(self):
        '''
        Test case for Config.get('strang', 'default')
        '''
        assert self.config.get('strang', 'default') == 'default'

    def test_get_conf(self):
        '''
        Test case for Config.get('env') returning value from self.conf
        '''
        self.config.conf['env'] = {'mock': True}
        assert self.config.get('env') == {'mock': True}
Пример #9
0
class Compress(object):

    def __init__(self, path):
        self.appdir = path
        self.attach_dir = os.path.join(path, '_attachments')
        self.conf = Config()
        self.conf.update(path)

    def is_hook(self):
        if not 'compress' in self.conf:
            return False
        return True

    def compress_css(self, css):
        re_url = re.compile('url\s*\(([^\s"].*)\)')

        src_fpath = ''
        fname_dir = ''

        def replace_url(mo):
            """ make sure urls are relative to css path """
            css_url = mo.group(0)[4:].strip(")").replace("'", "").replace('"',
                                                                          '')
            css_path = os.path.join(os.path.dirname(src_fpath), css_url)

            rel_path = util.relpath(css_path, fname_dir)
            return "url(%s)" % rel_path

        for fname, src_files in css.iteritems():
            output_css = ''

            dest_path = os.path.join(self.attach_dir, fname)
            fname_dir = os.path.dirname(dest_path)

            for src_fname in src_files:
                src_fpath = os.path.join(self.appdir, src_fname)

                if os.path.exists(src_fpath):
                    content_css = \
                        str(compress_css.CSSParser(util.read(src_fpath)))
                    content_css = re_url.sub(replace_url, content_css)
                    output_css += content_css
                    logger.debug("Merging %s in %s" % (src_fname, fname))

            if not os.path.isdir(fname_dir):
                os.makedirs(fname_dir)
            util.write(dest_path, output_css)

    def compress_js(self, backend, js):
        logger.info("compress js with %s " % backend.__about__)

        for fname, src_files in js.iteritems():
            output_js = ''

            dest_path = os.path.join(self.attach_dir, fname)
            fname_dir = os.path.dirname(dest_path)

            for src_fname in src_files:
                src_fpath = os.path.join(self.appdir, src_fname)
                if os.path.isfile(src_fpath):
                    output_js += "/* %s */\n" % src_fpath
                    output_js += util.read(src_fpath)
                    logger.debug("merging %s in %s" % (src_fname, fname))

            if not os.path.isdir(fname_dir):
                os.makedirs(fname_dir)

            output_js = backend.compress(output_js)
            util.write(dest_path, output_js)

    def run(self):
        conf = self.conf
        actions = conf.get('compress', {})
        if 'css' in actions:
            self.compress_css(actions['css'])

        if 'js' in actions:
            if 'js_compressor' in conf['compress']:
                modname = conf['compress']['js_compressor']
                if not isinstance(modname, basestring):
                    logger.warning("Warning: js_compressor settings should " +
                                   "be a string")
                    logger.warning("Selecting default backend (jsmin)")
                    import couchapp.hooks.compress.default as backend
                else:
                    try:
                        backend = __import__(modname, {}, {}, [''])
                    except ImportError:
                        import couchapp.hooks.compress.default as backend
            else:
                import couchapp.hooks.compress.default as backend
            self.compress_js(backend, actions['js'])
Пример #10
0
 def __init__(self):
   self.conf = Config()
   self.db = self.conf.get_dbs()[0]
Пример #11
0
class Fulfillment(object):
  def __init__(self):
    self.conf = Config()
    self.db = self.conf.get_dbs()[0]
    
  def run(self):
    self.build_edocs()
    for doc_id in os.listdir('_docs'):
      self.build_js(doc_id)
  
  def build_edocs(self, doc_id=None):
    env = self.get_local_env(doc_id)
    edocs = env['edocs']
    if len(edocs) > 0:
      if not os.path.exists(self.doc_path('edocs', doc_id)):
        os.mkdir(self.doc_path('edocs', doc_id))
      for edoc_id, edoc_opts in edocs.items():
        edoc = self.db.open_doc(edoc_id)
        for field in ['_id', '_rev', 'couchapp']:
          if field in edoc:
            if field not in ('_rev', 'edocs'):
              edoc['edoc_' + field] = edoc[field];
            del edoc[field]
        self.write_if_changed(self.doc_path('edocs/%s.json' % edoc_id, doc_id), edoc)
  
  def build_js(self, doc_id=None):
    env = self.get_local_env(doc_id)
    if env.has_key('script') and env['script'].get('build_module', False):
      resp = self.db.res.get('/_design/kvjs/_show/script/%s' % doc_id)
      self.write_if_changed(self.doc_path('%s.js' % doc_id, doc_id), resp.body_string())
  
  def write_if_changed(self, pth, val):
    verb = 'Created'
    if os.path.exists(pth):
      verb = 'Updated'
      with open(pth) as f:
        if type(val) == str:
          if val == f.read():
            return False
        else:
          if val == json.load(f):
            return False
    with open(pth, 'w') as f:
      if type(val) == str:
        f.write(val)
      else:
        json.dump(val, f, indent=2, sort_keys=True)
    print '%s %s' % (verb, pth)
  
  def doc_path(self, path, doc_id=None):
    if doc_id is None:
      return path
    else:
      return "_docs/%s/%s" % (doc_id, path)
  
  def get_local_env(self, doc_id):
    env_path = self.doc_path('env.json', doc_id)
    if os.path.exists(env_path):
      with open(env_path) as f:
        return json.load(f)
    return {}
Пример #12
0
 def setup(self, rcpath, getcwd):
     self.config = Config()
Пример #13
0
class TestConfig():
    @patch('couchapp.config.util.findcouchapp', return_value=None)
    @patch('couchapp.config.util.rcpath', return_value=['/mock/couchapp.conf'])
    def setup(self, rcpath, getcwd):
        self.config = Config()

    def teardown(self):
        del self.config

    @raises(AttributeError)
    def test_getattr(self):
        '''
        Test case for Config.__getattr__()
        '''
        assert self.config.conf == Config.DEFAULTS
        assert self.config.env == {}
        self.config.mock  # raise AttributeError

    @raises(KeyError)
    def test_getitem(self):
        '''
        Test case for Config.__getitem__()
        '''
        assert self.config['conf'] == Config.DEFAULTS
        assert self.config['env'] == {}
        assert self.config['mock']  # raise KeyError

    def test_contains(self):
        '''
        Test case for Config.__contains__()
        '''
        assert 'env' in self.config
        assert 'hooks' in self.config
        assert 'extensions' in self.config

    @patch('couchapp.config.util.read_json', return_value={'mock': True})
    @patch('couchapp.config.os.path.isfile', return_value=True)
    def test_load_from_list(self, isfile, read_json):
        '''
        Test case for Config.load(list, default)
        '''
        default = {'foo': 'bar'}

        conf = self.config.load(['/mock/couchapp.conf'], default)

        assert conf == {'foo': 'bar', 'mock': True}
        isfile.assert_called_with('/mock/couchapp.conf')
        read_json.assert_called_with('/mock/couchapp.conf',
                                     use_environment=True,
                                     raise_on_error=True)

    @patch('couchapp.config.util.read_json', return_value={'mock': True})
    @patch('couchapp.config.os.path.isfile', return_value=True)
    def test_load_from_str(self, isfile, read_json):
        '''
        Test case for Config.load(str)
        '''
        conf = self.config.load('/mock/couchapp.conf')

        assert conf == {'mock': True}
        isfile.assert_called_with('/mock/couchapp.conf')
        read_json.assert_called_with('/mock/couchapp.conf',
                                     use_environment=True,
                                     raise_on_error=True)

    @patch('couchapp.config.util.read_json', return_value={'mock': True})
    @patch('couchapp.config.os.path.isfile', return_value=False)
    def test_load_notfile(self, isfile, read_json):
        '''
        Test case for Config.load(['/not_a_file'], default)
        '''
        default = {'foo': 'bar'}

        conf = self.config.load(['/not_a_file'], default)

        assert conf == {'foo': 'bar'}
        isfile.assert_called_with('/not_a_file')
        assert not read_json.called

    @raises(AppError)
    @patch('couchapp.config.util.read_json', side_effect=ValueError)
    @patch('couchapp.config.os.path.isfile', return_value=True)
    def test_load_apperror(self, isfile, read_json):
        '''
        Test case for Config.load() reading a invalid file
        '''
        self.config.load('/mock/couchapp.conf')
        isfile.assert_called_with('/mock/couchapp.conf')

    @patch('couchapp.config.util.read_json', return_value={'mock': True})
    @patch('couchapp.config.os.path.isfile', return_value=True)
    def test_load_deepcopy_default(self, isfile, read_json):
        '''
        Test case for checking Config.load() deepcopy param ``default``
        '''
        default = {'foo': {'bar': 'fake'}}

        conf = self.config.load('/mock.conf', default=default)

        assert conf == {'foo': {'bar': 'fake'}, 'mock': True}
        assert default == {'foo': {'bar': 'fake'}}

    @patch('couchapp.config.Config.load', return_value='mock')
    def test_load_local(self, load):
        '''
        Test case for Config.load_local()
        '''
        assert self.config.load_local('/mock') == 'mock'

        paths = (load.call_args_list[0][0][0], load.call_args_list[1][0][0])
        assert paths == ('/mock/couchapp.json', '/mock/.couchapprc'), paths

    @raises(AppError)
    @patch('couchapp.config.Config.load')
    def test_load_local_apperror(self, load):
        '''
        Test case for Config.load_local() with empty `app_dir`
        '''
        self.config.load_local(None)
        assert not load.called

    @patch('couchapp.config.Config.load')
    def test_load_local_prevent_env(self, load):
        '''
        Test case for Config.load_local() with ``env`` field in ``couchapp.json``
        '''
        def load_side_effect(path, default={}):
            print(path == '/mock/couchapp.json', path)
            if path == '/mock/couchapp.json':
                default.update({'env': 'fake_env', 'name': 'MockApp'})
            elif path == '/mock/.couchapprc':
                default.update({'hook': 'mock_hook'})
            else:
                raise AssertionError(
                    'Unknown local config file "{}"'.format(path))
            return default

        load.side_effect = load_side_effect
        conf = self.config.load_local('/mock')

        assert conf['name'] == 'MockApp'
        assert conf['hook'] == 'mock_hook'
        assert conf.get('env', None) is None

    @patch('couchapp.config.Config.load_local', return_value={'mock': True})
    def test_update(self, load_local):
        '''
        Test case for Config.update()
        '''
        self.config.update('/mock')

        assert self.config.conf.get('mock') == True
        load_local.assert_called_with('/mock')

    @patch('couchapp.config.util.load_py')
    def test_extensions_empty(self, load_py):
        '''
        Test case for empty Config.extensions
        '''
        assert self.config.extensions == []
        assert not load_py.called

    @patch('couchapp.config.util.load_py', return_value='mock')
    def test_extensions_mock(self, load_py):
        '''
        Test case for Config.extensions
        '''
        self.config.conf['extensions'] = ['mock_path']
        extensions = self.config.extensions

        assert extensions == ['mock'], extensions
        load_py.assert_called_with('mock_path', self.config)

    @patch('couchapp.config.util.hook_uri')
    def test_hook_empty(self, hook_uri):
        '''
        Test case for empty Config.hooks
        '''
        assert self.config.hooks == {}
        assert not hook_uri.called

    @patch('couchapp.config.util.hook_uri', return_value='mock_module')
    def test_hook_mock(self, hook_uri):
        '''
        Test case for Config.hooks
        '''
        self.config.conf['hooks'] = {'pre-push': ['mock_path']}
        hooks = self.config.hooks

        assert hooks == {'pre-push': ['mock_module']}, hooks
        hook_uri.assert_called_with('mock_path', self.config)

    @patch('couchapp.config.Database', return_value='mockdb')
    def test_get_dbs_full_uri(self, Database):
        '''
        Test case for Config.get_dbs() with full uri
        '''
        db_string = 'https://foo.bar'

        assert self.config.get_dbs(db_string) == ['mockdb']
        Database.assert_called_with(db_string, use_proxy=False)

    @patch('couchapp.config.Database', return_value='mockdb')
    def test_get_dbs_short_uri(self, Database):
        '''
        Test case for Config.get_dbs() with short uri
        '''
        full_uri = 'http://127.0.0.1:5984/foo'

        assert self.config.get_dbs('foo') == ['mockdb']
        Database.assert_called_with(full_uri, use_proxy=False)

    @patch('couchapp.config.Database', return_value='mockdb')
    def test_get_dbs_env(self, Database):
        '''
        Test case for Config.get_dbs() with env set
        '''
        db_string = 'http://foo.bar'
        self.config.conf['env'] = {'default': {'db': db_string}}

        assert self.config.get_dbs() == ['mockdb']
        Database.assert_called_with(db_string, use_proxy=False)

    @raises(AppError)
    @patch('couchapp.config.Database')
    def test_get_dbs_empty_env(self, Database):
        '''
        Test case for Config.get_dbs() without env set
        '''
        self.config.get_dbs()
        assert not Database.called

    @patch('couchapp.config.Database', return_value='mockdb')
    def test_get_dbs_short_env(self, Database):
        '''
        Test case for Config.get_dbs() with a short name in env
        '''
        self.config.conf['env'] = {'foo': {'db': 'http://foo.bar'}}

        assert self.config.get_dbs('foo') == ['mockdb']
        Database.assert_called_with('http://foo.bar', use_proxy=False)

    @patch('couchapp.config.Database', return_value='mockdb')
    def test_get_dbs_env_fake(self, Database):
        '''
        Test case for Config.get_dbs() with an useless env

        Assume .couchapprc is (no `db` field in `foo`)
        ```
        {
            'foo':{
                'notdb': 'mock'
            }
        }
        ```

        Expect behavior: fall back to DEFAULT_SERVER_URI/foo
        '''
        self.config.conf['env'] = {'foo': {'notdb': 'mock'}}
        default_uri = 'http://127.0.0.1:5984/foo'

        assert self.config.get_dbs('foo') == ['mockdb']
        Database.assert_called_with(default_uri, use_proxy=False)

    @patch('couchapp.config.Database', return_value='mockdb')
    def test_get_dbs_proxy(self, Database):
        '''
        Test case for Config.get_dbs() with https_proxy env
        '''
        with patch.dict('couchapp.config.os.environ', {'https_proxy': 'foo'}):
            assert self.config.get_dbs('https://bar') == ['mockdb']

        Database.assert_called_with('https://bar', use_proxy=True)

    def test_get_app_name_default(self):
        '''
        Test case for Config.get_app_name() without args and env
        '''
        assert self.config.get_app_name() == None

    def test_get_app_name_default_env(self):
        '''
        Test case for Config.get_app_name() without args but env

        env: {
            'default': {
                'name': 'MockApp'
            }
        }
        and
        env: {
            'mockname': {
                'name': 'MockApp2'
            }
        }
        '''
        self.config.conf['env'] = {'default': {'name': 'MockApp'}}
        assert self.config.get_app_name() == 'MockApp'

        self.config.conf['env'] = {'mockname': {'name': 'MockApp2'}}
        assert self.config.get_app_name('mockname') == 'MockApp2'

        self.config.conf['env'] = {'default': {'name': 'MockApp3'}}
        assert self.config.get_app_name('strang') == 'MockApp3'

    def test_get_app_name_http_uri(self):
        '''
        Test case for Config.get_app_name('http://foo.bar', default)

        If the dbstring is full uri, return ``default``
        '''
        ret = self.config.get_app_name('http://foo.bar', 'mockapp')
        assert ret == 'mockapp'

    def test_iter(self):
        '''
        Test case for Config.__iter__()
        '''
        self.config.conf['env'] = {'mock': True}
        ls = list(self.config)

        assert ('env', {'mock': True}) in ls, ls
        assert ('hooks', {}) in ls, ls

    def test_get(self):
        '''
        Test case for Config.get('__init__')
        '''
        assert callable(self.config.get('__init__'))

    def test_get_default(self):
        '''
        Test case for Config.get('strang', 'default')
        '''
        assert self.config.get('strang', 'default') == 'default'

    def test_get_conf(self):
        '''
        Test case for Config.get('env') returning value from self.conf
        '''
        self.config.conf['env'] = {'mock': True}
        assert self.config.get('env') == {'mock': True}
Пример #14
0
 def __init__(self, path):
     self.appdir = path
     self.attach_dir = os.path.join(path, '_attachments')
     self.conf = Config()
     self.conf.update(path)
Пример #15
0
 def setup(self, rcpath, getcwd):
     self.config = Config()
class Compress(object):
    def __init__(self, path):
        self.appdir = path
        self.attach_dir = os.path.join(path, '_attachments')
        self.conf = Config()
        self.conf.update(path)

    def is_hook(self):
        if not 'compress' in self.conf:
            return False
        return True

    def compress_css(self, css):
        re_url = re.compile('url\s*\(([^\s"].*)\)')

        src_fpath = ''
        fname_dir = ''

        def replace_url(mo):
            """ make sure urls are relative to css path """
            css_url = mo.group(0)[4:].strip(")").replace("'",
                                                         "").replace('"', '')
            css_path = os.path.join(os.path.dirname(src_fpath), css_url)

            rel_path = util.relpath(css_path, fname_dir)
            return "url(%s)" % rel_path

        for fname, src_files in css.iteritems():
            output_css = ''

            dest_path = os.path.join(self.attach_dir, fname)
            fname_dir = os.path.dirname(dest_path)

            for src_fname in src_files:
                src_fpath = os.path.join(self.appdir, src_fname)

                if os.path.exists(src_fpath):
                    content_css = str(
                        compress_css.CSSParser(util.read(src_fpath)))
                    content_css = re_url.sub(replace_url, content_css)
                    output_css += content_css
                    logger.debug("Merging %s in %s" % (src_fname, fname))

            if not os.path.isdir(fname_dir):
                os.makedirs(fname_dir)
            util.write(dest_path, output_css)

    def compress_js(self, backend, js):
        logger.info("compress js with %s " % backend.__about__)

        for fname, src_files in js.iteritems():
            output_js = ''

            dest_path = os.path.join(self.attach_dir, fname)
            fname_dir = os.path.dirname(dest_path)

            for src_fname in src_files:
                src_fpath = os.path.join(self.appdir, src_fname)
                if os.path.isfile(src_fpath):
                    output_js += "/* %s */\n" % src_fpath
                    output_js += util.read(src_fpath)
                    logger.debug("merging %s in %s" % (src_fname, fname))

            if not os.path.isdir(fname_dir):
                os.makedirs(fname_dir)

            output_js = backend.compress(output_js)
            util.write(dest_path, output_js)

    def run(self):
        conf = self.conf
        actions = conf.get('compress', {})
        if 'css' in actions:
            self.compress_css(actions['css'])

        if 'js' in actions:
            if 'js_compressor' in conf['compress']:
                modname = conf['compress']['js_compressor']
                if not isinstance(modname, basestring):
                    logger.warning(
                        "Warning: js_compressor settings should be a string")
                    logger.warning("Selecting default backend (jsmin)")
                    import couchapp.hooks.compress.jsmin as backend
                else:
                    try:
                        backend = __import__(modname, {}, {}, [''])
                    except ImportError:
                        import couchapp.hooks.compress.jsmin as backend
            else:
                import couchapp.hooks.compress.jsmin as backend
            self.compress_js(backend, actions['js'])
 def __init__(self, path):
     self.appdir = path
     self.attach_dir = os.path.join(path, '_attachments')
     self.conf = Config()
     self.conf.update(path)