Permalink
Browse files

Inject CSS/JSSource only once.

  • Loading branch information...
Cito committed Oct 8, 2012
1 parent cbf6032 commit ae13c369a552cb71c1156a817412582f6454406f
Showing with 48 additions and 14 deletions.
  1. +33 −5 tests/test_resources.py
  2. +12 −6 tw2/core/resources.py
  3. +3 −3 tw2/core/util.py
@@ -32,13 +32,13 @@ def setUp(self):
def test_res_collection(self):
rl = testapi.request(1, mw)
wa = TestWidget(id='a')
wb = TestWidget(id='b', resources=[js,css])
wb = TestWidget(id='b', resources=[js, css])
wa.display()
rl = twc.core.request_local()
assert(len(rl.get('resources', [])) == 0)
wb.display()
for r in rl['resources']:
assert(any(isinstance(r, b) for b in [js,css]))
assert(any(isinstance(r, b) for b in [js, css]))
rl = testapi.request(2)
r = rl.get('resources', [])
assert len(r) == 0, r
@@ -187,6 +187,34 @@ def test_inject_both(self):
<title>a</title></head><body>hello<script type="text/javascript">bob</script>\
</body></html>')
def test_inject_js_twice(self):
rl = testapi.request(1, mw)
js.inject()
js.inject()
out = twc.inject_resources(html)
print out
assert eq_xhtml(out, '<html><head>\
<script type="text/javascript" src="paj"></script>\
<title>a</title></head><body>hello</body></html>')
def test_inject_jssrc_twice(self):
rl = testapi.request(1, mw)
jssrc.inject()
jssrc.inject()
out = twc.inject_resources(html)
assert eq_xhtml(out, '<html><head>\
<title>a</title></head><body>hello<script type="text/javascript">bob</script>\
</body></html>')
def test_inject_csssrc_twice(self):
rl = testapi.request(1, mw)
csssrc.inject()
csssrc.inject()
out = twc.inject_resources(html)
assert eq_xhtml(out, '<html><head>\
<style type="text/css">.bob { font-weight: bold; }</style>\
<title>a</title></head><body>hello</body></html>')
def test_detect_clear(self):
widget = twc.Widget(id='a', template='genshi:tw2.core.test_templates.inner_genshi', test='test', resources=[js])
rl = testapi.request(1, mw)
@@ -286,7 +314,7 @@ def test_display(self):
displays.append(r.display(template='%s:%s' % (e, twr.JSSource.template)))
compare_to = str(displays[0]).strip()
equal_displays = filter(lambda x:str(x).strip()==compare_to, displays)
equal_displays = filter(lambda x: str(x).strip() == compare_to, displays)
assert len(displays) == len(equal_displays), equal_displays
class TestCSSSourceEscaping(tb.WidgetTest):
@@ -310,7 +338,7 @@ def test_display(self):
displays.append(r.display(template='%s:%s' % (e, twr.CSSSource.template)))
compare_to = str(displays[0]).strip()
equal_displays = filter(lambda x:str(x).strip()==compare_to, displays)
equal_displays = filter(lambda x: str(x).strip() == compare_to, displays)
assert len(displays) == len(equal_displays), equal_displays
from pkg_resources import Requirement
@@ -338,7 +366,7 @@ def testJSSymbol(self):
should set the src attribute
"""
s = twr.JSSymbol("source")
self.assert_(s.src=="source")
self.assert_(s.src == "source")
def testEncoderDefault(self):
enc = twc.encoder
@@ -176,11 +176,9 @@ def __hash__(self):
)
def __eq__(self, other):
attrs = ['link', 'modname', 'filename']
return all([
getattr(self, attr, None) == getattr(other, attr, None)
for attr in attrs
])
return (isinstance(other, Link) and self.link == other.link
and self.modname == other.modname
and self.filename == other.filename)
def __repr__(self):
return "%s('%s')" % (
@@ -227,6 +225,9 @@ class JSSource(Resource):
location = 'bodybottom'
template = 'tw2.core.templates.jssource'
def __eq__(self, other):
return isinstance(other, JSSource) and self.src == other.src
def __repr__(self):
return "%s('%s')" % (self.__class__.__name__, self.src)
@@ -236,6 +237,7 @@ def prepare(self):
raise ValueError("%r must be provided a 'src' attr" % self)
self.src = Markup(self.src)
class CSSSource(Resource):
"""
Inline Cascading Style-Sheet code.
@@ -244,6 +246,9 @@ class CSSSource(Resource):
location = 'head'
template = 'tw2.core.templates.csssource'
def __eq__(self, other):
return isinstance(other, CSSSource) and self.src == other.src
def __repr__(self):
return "%s('%s')" % (self.__class__.__name__, self.src)
@@ -253,6 +258,7 @@ def prepare(self):
raise ValueError("%r must be provided a 'src' attr" % self)
self.src = Markup(self.src)
class _JSFuncCall(JSSource):
"""
Internal use inline JavaScript function call.
@@ -445,7 +451,7 @@ class _ResourceInjector(util.MultipleReplacer):
cannot be injected again (in the same request). This is useful in case
:class:`injector_middleware` is stacked so it doesn't inject them again.
Injecting them explicitly is neccesary if the response's body is being
Injecting them explicitly is necessary if the response's body is being
cached before the middleware has a chance to inject them because when the
cached version is served no widgets are being rendered so they will not
have a chance to register their resources.
@@ -47,7 +47,7 @@ class MultipleReplacer(object):
"""Performs several regexp substitutions on a string with a single pass.
``dct`` is a dictionary keyed by a regular expression string and with a
callable as value that will get called to produce a subsituted value.
callable as value that will get called to produce a substituted value.
The callable takes the matched text as first argument and may take any
number of positional and keyword arguments. These arguments are any extra
@@ -79,7 +79,7 @@ def __repr__(self):
return "<%s at %d (%r)>" % (self.__class__.__name__, id(self),
self._raw_regexp)
def _subsitutor(self, *args, **kw):
def _substitutor(self, *args, **kw):
def substitutor(match):
tuples = itertools.izip(self._substitutors, match.groups())
for substitutor, group in tuples:
@@ -88,7 +88,7 @@ def substitutor(match):
return substitutor
def __call__(self, string, *args, **kw):
return self._regexp.sub(self._subsitutor(*args, **kw), string)
return self._regexp.sub(self._substitutor(*args, **kw), string)
def abort(req, status):

0 comments on commit ae13c36

Please sign in to comment.