diff --git a/.coveragerc b/.coveragerc index ba3367f1..9f7f9df1 100644 --- a/.coveragerc +++ b/.coveragerc @@ -4,8 +4,9 @@ omit = *pulsar/utils/system/winservice.py *pulsar/utils/system/windowssystem.py *pulsar/utils/system/winprocess.py + *pulsar/utils/system/appengine.py *pulsar/async/cov.py - *pulsar/async/fallbacks/asyncio.py + *pulsar/async/appengine.py *pulsar/apps/test/plugins/bench.py *pulsar/apps/test/cov.py *pulsar/apps/test/plugins/profile.py @@ -16,6 +17,7 @@ omit = examples/pshell/* examples/snippets/* examples/pulsards/* + examples/tweets/* diff --git a/pulsar/apps/wsgi/content.py b/pulsar/apps/wsgi/content.py index 351d949c..4110bae5 100644 --- a/pulsar/apps/wsgi/content.py +++ b/pulsar/apps/wsgi/content.py @@ -150,7 +150,7 @@ from pulsar import multi_async, Future, async, coroutine_return, chain_future from pulsar.utils.pep import iteritems, is_string, to_string, ispy3k -from pulsar.utils.html import (slugify, INLINE_TAGS, tag_attributes, attr_iter, +from pulsar.utils.html import (slugify, INLINE_TAGS, escape, dump_data_value, child_tag) from pulsar.utils.httpurl import remove_double_slash from pulsar.utils.system import json @@ -213,6 +213,12 @@ def stream_mapping(value, request=None): return multi_async(result) +def attr_iter(attrs): + for k, v in iteritems(attrs): + if v is not None: + yield " %s='%s'" % (k, escape(v, force=True)) + + class AsyncString(object): '''An asynchronous string which can be used with pulsar WSGI servers. ''' @@ -498,9 +504,6 @@ class Html(AsyncString): * ``data`` dictionary of data to add (rendered as HTML data attribute). * ``type`` type of element, only supported for tags which accept the ``type`` attribute (for example the ``input`` tag). - - Any other keyed-value parameter will be added as attribute, - if in the set of:attr:`available_attributes` or as :meth:`data`. ''' _default_content_type = 'text/html' @@ -545,11 +548,6 @@ def type(self): if 'attr' in self._extra: return self._extra['attr'].get('type') - @property - def available_attributes(self): - '''The list of valid HTML attributes for this :attr:`tag`.''' - return tag_attributes(self._tag, self.type) - def get_form_value(self): '''Return the value of this :class:`Html` element when it is contained in a Html form element. @@ -582,7 +580,7 @@ def append(self, child): child = Html(tag, child) super(Html, self).append(child) - def _setup(self, cn=None, attr=None, css=None, data=None, type=None, + def _setup(self, cn=None, attr=None, css=None, data=None, content_type=None, **params): self.charset = params.get('charset') or 'utf-8' self._content_type = content_type or self._default_content_type @@ -591,15 +589,7 @@ def _setup(self, cn=None, attr=None, css=None, data=None, type=None, self.data(data) self.attr(attr) self.css(css) - attributes = self.available_attributes - if type and 'type' in attributes: - self.attr('type', type) - attributes = self.available_attributes - for name, value in iteritems(params): - if name in attributes: - self.attr(name, value) - elif name != 'charset': - self.data(name, value) + self.attr(params) def attr(self, *args): '''Add the specific attribute to the attribute dictionary @@ -611,13 +601,7 @@ def attr(self, *args): if adding: if attr is None: self._extra['attr'] = attr = {} - available_attributes = self.available_attributes - for name, value in iteritems(result): - if value is not None: - if name in available_attributes: - attr[name] = value - elif name is 'value': - self.append(value) + attr.update(result) result = self return result diff --git a/pulsar/utils/html.py b/pulsar/utils/html.py index d2e9e61c..8b7a0abc 100644 --- a/pulsar/utils/html.py +++ b/pulsar/utils/html.py @@ -10,61 +10,8 @@ NOTHING = ('', b'', None) '''Tuple of elements considered as null.''' INLINE_TAGS = set(('input', 'link', 'meta', 'hr')) -# The global attributes below can be used on any HTML element -# class and style are misssing here since they are treated separately -GLOBAL_HTML_ATTRIBUTES = ('accesskey', 'contenteditable', 'contextmenu', 'dir', - 'draggable', 'dropzone', 'hidden', 'id', 'lang', - 'spellcheck', 'tabindex', 'title', 'translate') -HTML_ATTRIBUTES = {} -HTML_CHILDREN_TAG = {} - -# Extend GLOBAL ATTRIBUTES (which can be used in any HTML element). -e = lambda *t: GLOBAL_HTML_ATTRIBUTES + t - -# Input atg attributes -# http://www.w3schools.com/tags/tag_input.asp -input_attr = lambda *t: e('type', 'autocomplete', 'autofocus', 'disabled', - 'form', 'formnovalidate', 'list', 'max', 'maxlength', - 'min', 'multiple', 'name', 'pattern', 'placeholder', - 'readonly', 'required', 'size', 'step', 'value', *t) - -# HTML TAG ATTRIBUTES -############################################################################ -HTML_ATTRIBUTES['a'] = e('href', 'name', 'target') -HTML_ATTRIBUTES['form'] = e('accept-charset', 'action', 'autocomplete', - 'enctype', 'method', 'name', 'novalidate', - 'target') -HTML_ATTRIBUTES['img'] = e('align', 'alt', 'broder', 'crossorigin', - 'height', 'hspace', 'ismap', 'longdesc', - 'src', 'usemap', 'vspace', 'width') -HTML_ATTRIBUTES['input'] = input_attr() -HTML_ATTRIBUTES['input[type="checkbox"]'] = input_attr('checked') -HTML_ATTRIBUTES['input[type="file"]'] = input_attr('accept') -HTML_ATTRIBUTES['input[type="image"]'] = input_attr( - 'alt', 'formaction', 'formenctype', 'formmethod', 'formtarget', - 'height', 'src', 'width') -HTML_ATTRIBUTES['input[type="radio"]'] = input_attr('checked') -HTML_ATTRIBUTES['input[type="submit"]'] = input_attr( - 'formaction', 'formenctype', 'formmethod', 'formtarget') -HTML_ATTRIBUTES['link'] = e('href', 'hreflang', 'media', 'rel', - 'sizes', 'type') -HTML_ATTRIBUTES['meta'] = e('charset', 'content', 'http-equiv', 'name', - 'scheme') -HTML_ATTRIBUTES['option'] = e('disabled', 'label', 'selected', 'value') -HTML_ATTRIBUTES['script'] = e('async', 'charset', 'defer', 'src', 'type') -HTML_ATTRIBUTES['style'] = e('media', 'scoped', 'type') -HTML_ATTRIBUTES['select'] = e('autofocus', 'disabled', 'form', 'multiple', - 'name', 'required', 'size') -HTML_ATTRIBUTES['textarea'] = e('autofocus', 'cols', 'disabled', 'maxlength', - 'name', 'placeholder', 'readonly', 'required', - 'rows', 'wrap') -HTML_ATTRIBUTES['th'] = e('colspan', 'headers', 'rowspan', 'scope') - -# DEFAULT HTML TAG CHILDREN -############################################################################ -HTML_CHILDREN_TAG['ul'] = 'li' -HTML_CHILDREN_TAG['ol'] = 'li' -HTML_CHILDREN_TAG['select'] = 'option' +HTML_CHILDREN_TAG = {'ul': 'li', + 'ol': 'li'} # COMMON HTML ENTITIES # Check http://www.w3schools.com/tags/ref_symbols.asp for more @@ -83,17 +30,6 @@ '''HTML -- symbol.''' -def tag_attributes(tag, type=None): - '''Return a tuple of valid attributes for the HTML ``tag`` and optional -``type``. If the ``tag`` is not found in the global ``HTML_ATTRIBUTES`` -dictionary, the ``GLOBAL_HTML_ATTRIBUTES`` set is returned.''' - if type: - ntag = '%s[type="%s"]' % (tag, type) - if ntag in HTML_ATTRIBUTES: - return HTML_ATTRIBUTES[ntag] - return HTML_ATTRIBUTES.get(tag, GLOBAL_HTML_ATTRIBUTES) - - def child_tag(tag): '''The default children ``tag`` for a given ``tag``.''' return HTML_CHILDREN_TAG.get(tag) @@ -130,12 +66,6 @@ def escape(html, force=False): '"', '"') -def attr_iter(attrs): - for k, v in iteritems(attrs): - if v is not None: - yield " %s='%s'" % (k, escape(v, force=True)) - - def dump_data_value(v): if not is_string(v): if isinstance(v, bytes): diff --git a/tests/wsgi/html.py b/tests/wsgi/html.py index d2c6fba7..978dd1b8 100644 --- a/tests/wsgi/html.py +++ b/tests/wsgi/html.py @@ -22,10 +22,10 @@ def testEmpty(self): self.assertEqual(c._data, None) self.assertEqual(c._css, None) - def testHtmlRepr(self): + def test_html_repr(self): c = wsgi.Html('div', cn='bla', charset='utf-16') self.assertEqual(c.content_type, 'text/html; charset=utf-16') - self.assertEqual(str(c), "
") + self.assertEqual(str(c), "
") c = wsgi.Html(None, cn='bla') self.assertEqual(c.tag, None) self.assertEqual(str(c), "Html") @@ -119,14 +119,13 @@ def testHide(self): class TestWidgets(unittest.TestCase): - def testAncor(self): + def test_ancor(self): a = wsgi.Html('a', 'kaput', cn='bla', href='/abc/') self.assertEqual(a.attr('href'), '/abc/') ht = a.render() self.assertTrue('>kaput' in ht) a = wsgi.Html('a', xxxx='ciao') - self.assertFalse('xxxx' in a.attr()) - self.assertEqual(a.data('xxxx'), 'ciao') + self.assertTrue('xxxx' in a.attr()) def testList(self): ul = wsgi.Html('ul') @@ -170,7 +169,7 @@ def test_document_empty_body(self): txt = m.render() self.assertEqual(txt, ''.join(['\n', - "\n", + "\n", '', 'test' "",