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")
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')
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
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()
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
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
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)
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}
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'])
def __init__(self): self.conf = Config() self.db = self.conf.get_dbs()[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 {}
def setup(self, rcpath, getcwd): self.config = Config()
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}
def __init__(self, path): self.appdir = path self.attach_dir = os.path.join(path, '_attachments') self.conf = Config() self.conf.update(path)
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'])