Commit b0fd409b authored by Sylvain Thénault's avatar Sylvain Thénault
Browse files

[uiprops] test and fix reloading of modified css files; update c-c newcube;...

[uiprops] test and fix reloading of modified css files; update c-c newcube; deprecates config.has_resource.
parent 76b828dc3b9f
......@@ -181,10 +181,6 @@ class BaseApptestConfiguration(TestServerConfiguration, TwistedConfiguration):
def available_languages(self, *args):
return ('en', 'fr', 'de')
def ext_resources_file(self):
"""return instance's external resources file"""
return join(self.apphome, 'data', 'external_resources')
def pyro_enabled(self):
# but export PYRO_MULTITHREAD=0 or you get problems with sqlite and threads
return True
......
......@@ -595,7 +595,7 @@ layout, and a full featured cube with "full" layout.',
exclude = SKEL_EXCLUDE
if self['layout'] == 'simple':
exclude += ('sobjects.py*', 'precreate.py*', 'realdb_test*',
'cubes.*', 'external_resources*')
'cubes.*', 'uiprops.py*')
copy_skeleton(skeldir, cubedir, context, exclude=exclude)
def _ask_for_dependencies(self):
......
# -*- shell-script -*-
###############################################################################
#
# put here information about external resources used by your components,
# or to overides existing external resources configuration
# Put here information about external resources / styles used by your cube,
# or to overides existing UI properties.
#
# Existing properties are available through the `sheet` dictionary available
# in the global namespace. You also have access to a `data` function which
# will return proper url for resources in the 'data' directory.
#
# /!\ this file should not be imported /!\
###############################################################################
# CSS stylesheets to include in HTML headers
# uncomment the line below to use template specific stylesheet
# STYLESHEETS = DATADIR/cubes.%(cubename)s.css
# STYLESHEETS = sheet['STYLESHEETS'] + [data('cubes.%(cubename)s.css')]
......@@ -56,21 +56,25 @@ class VRegistryTC(TestCase):
def test_load_subinterface_based_appobjects(self):
self.vreg.reset()
self.vreg.register_objects([join(BASE, 'web', 'views', 'iprogress.py')])
# check progressbar was kicked
self.failIf(self.vreg['views'].get('progressbar'))
# we've to emulate register_objects to add custom MyCard objects
path = [join(BASE, 'entities', '__init__.py'),
join(BASE, 'web', 'views', 'iprogress.py')]
filemods = self.vreg.init_registration(path, None)
for filepath, modname in filemods:
self.vreg.load_file(filepath, modname)
class MyCard(Card):
__implements__ = (IMileStone,)
self.vreg.reset()
self.vreg._loadedmods[__name__] = {}
self.vreg.register(MyCard)
self.vreg.register_objects([join(BASE, 'entities', '__init__.py'),
join(BASE, 'web', 'views', 'iprogress.py')])
self.vreg.initialization_completed()
# check progressbar isn't kicked
self.assertEquals(len(self.vreg['views']['progressbar']), 1)
def test_properties(self):
self.vreg.reset()
self.failIf('system.version.cubicweb' in self.vreg['propertydefs'])
self.failUnless(self.vreg.property_info('system.version.cubicweb'))
self.assertRaises(UnknownProperty, self.vreg.property_info, 'a.non.existent.key')
......
......@@ -47,12 +47,12 @@ class PropertySheet(dict):
self._ordered_propfiles.append(fpath)
def need_reload(self):
for rid, (adirectory, rdirectory, mtime) in self._cache.items():
if os.stat(osp.join(rdirectory, rid))[-2] > mtime:
del self._cache[rid]
for fpath, mtime in self._propfile_mtime.iteritems():
if os.stat(fpath)[-2] > mtime:
return True
for rid, (directory, mtime) in self._cache.items():
if os.stat(osp.join(directory, rid))[-2] > mtime:
del self._cache[rid]
return False
def reload(self):
......@@ -70,7 +70,7 @@ class PropertySheet(dict):
return self._cache[rid][0]
except KeyError:
cachefile = osp.join(self._cache_directory, rid)
self.debug('caching processed css %s/%s into %s',
self.debug('caching processed %s/%s into %s',
rdirectory, rid, cachefile)
rcachedir = osp.dirname(cachefile)
if not osp.exists(rcachedir):
......@@ -83,13 +83,14 @@ class PropertySheet(dict):
content = self.compile(content)
except ValueError, ex:
self.error("can't process %s/%s: %s", rdirectory, rid, ex)
adirectory = rdirectory
else:
stream = file(cachefile, 'w')
stream.write(content)
stream.close()
rdirectory = self._cache_directory
self._cache[rid] = (rdirectory, os.stat(sourcefile)[-2])
return rdirectory
adirectory = self._cache_directory
self._cache[rid] = (adirectory, rdirectory, os.stat(sourcefile)[-2])
return adirectory
def compile(self, content):
return self._percent_rgx.sub('%%', content) % self
......
import os
from os.path import join, dirname
from shutil import rmtree
from logilab.common.testlib import TestCase, unittest_main
from cubicweb.web.propertysheet import *
DATADIR = join(dirname(__file__), 'data')
CACHEDIR = join(DATADIR, 'uicache')
class PropertySheetTC(TestCase):
def tearDown(self):
rmtree(CACHEDIR)
def test(self):
ps = PropertySheet(None, datadir_url='http://cwtest.com')
ps = PropertySheet(CACHEDIR, datadir_url='http://cwtest.com')
ps.load(join(DATADIR, 'sheet1.py'))
ps.load(join(DATADIR, 'sheet2.py'))
# defined by sheet1
......@@ -20,6 +29,21 @@ class PropertySheetTC(TestCase):
'http://cwtest.com/mycube.css'])
self.assertEquals(ps.compile('a {bgcolor: %(bgcolor)s; size: 1%;}'),
'a {bgcolor: #FFFFFF; size: 1%;}')
self.assertEquals(ps.process_resource(DATADIR, 'pouet.css'),
CACHEDIR)
self.failUnless('pouet.css' in ps._cache)
self.failIf(ps.need_reload())
os.utime(join(DATADIR, 'sheet1.py'), None)
self.failUnless('pouet.css' in ps._cache)
self.failUnless(ps.need_reload())
self.failUnless('pouet.css' in ps._cache)
ps.reload()
self.failIf('pouet.css' in ps._cache)
self.failIf(ps.need_reload())
ps.process_resource(DATADIR, 'pouet.css') # put in cache
os.utime(join(DATADIR, 'pouet.css'), None)
self.failIf(ps.need_reload())
self.failIf('pouet.css' in ps._cache)
if __name__ == '__main__':
unittest_main()
......@@ -26,6 +26,7 @@ from os.path import join, exists, split
from warnings import warn
from logilab.common.decorators import cached
from logilab.common.deprecation import deprecated
from cubicweb.toolsutils import read_config
from cubicweb.cwconfig import CubicWebConfiguration, register_persistent_options, merge_options
......@@ -253,29 +254,30 @@ have the python imaging library installed to use captcha)',
user = unicode(user)
return user, passwd
def has_resource(self, rid):
"""return true if an external resource is defined"""
return bool(self.uiprops.get(rid))
@cached
def locate_resource(self, rid):
"""return the directory where the given resource may be found"""
return self._fs_locate(rid, 'data')
@cached
def locate_doc_file(self, fname):
"""return the directory where the given resource may be found"""
return self._fs_locate(fname, 'wdoc')
def _fs_locate(self, rid, rdirectory):
@cached
def _fs_path_locate(self, rid, rdirectory):
"""return the directory where the given resource may be found"""
path = [self.apphome] + self.cubes_path() + [join(self.shared_dir())]
for directory in path:
if exists(join(directory, rdirectory, rid)):
if rdirectory == 'data' and rid.endswith('.css'):
return self.uiprops.process_resource(join(directory, rdirectory),
rid)
return join(directory, rdirectory)
return directory
def _fs_locate(self, rid, rdirectory):
"""return the directory where the given resource may be found"""
directory = self._fs_path_locate(rid, rdirectory)
if directory is None:
return None
if rdirectory == 'data' and rid.endswith('.css'):
return self.uiprops.process_resource(join(directory, rdirectory), rid)
return join(directory, rdirectory)
def locate_all_files(self, rid, rdirectory='wdoc'):
"""return all files corresponding to the given resource"""
......@@ -319,11 +321,11 @@ have the python imaging library installed to use captcha)',
libuiprops = join(self.shared_dir(), 'data', 'uiprops.py')
self.uiprops.load(libuiprops)
for path in reversed([self.apphome] + self.cubes_path()):
self._load_ui_properties(join(path, 'data'))
self._load_ui_properties(path)
self._load_ui_properties(self.apphome)
def _load_ui_properties(self, path):
resourcesfile = join(path, 'external_resources')
resourcesfile = join(path, 'data', 'external_resources')
if exists(resourcesfile):
warn('[3.9] %s file is deprecated, use an uiprops.py file'
% resourcesfile, DeprecationWarning)
......@@ -367,3 +369,8 @@ have the python imaging library installed to use captcha)',
def static_file_del(self, rpath):
if self.static_file_exists(rpath):
os.remove(join(self.static_directory, rpath))
@deprecated('[3.9] use _cw.uiprops.get(rid)')
def has_resource(self, rid):
"""return true if an external resource is defined"""
return bool(self.uiprops.get(rid))
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment