Skip to content

Commit

Permalink
Fix nosamanuel#3 by re-working lib to use six
Browse files Browse the repository at this point in the history
Use six module to support both py2 and py3.
Add six as a dependency of cottonmouth.
  • Loading branch information
adamlwgriffiths committed Mar 22, 2021
1 parent 428a4b3 commit e83ee53
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 136 deletions.
220 changes: 111 additions & 109 deletions cottonmouth/constants.py
Original file line number Diff line number Diff line change
@@ -1,114 +1,116 @@
import six

HTML_VOID_TAGS = [
u'area',
u'base',
u'br',
u'col',
u'command',
u'embed',
u'hr',
u'img',
u'input',
u'keygen',
u'link',
u'meta',
u'param',
u'source',
u'track',
u'wbr',
six.u('area'),
six.u('base'),
six.u('br'),
six.u('col'),
six.u('command'),
six.u('embed'),
six.u('hr'),
six.u('img'),
six.u('input'),
six.u('keygen'),
six.u('link'),
six.u('meta'),
six.u('param'),
six.u('source'),
six.u('track'),
six.u('wbr'),
]

HTML_TAGS = [
u'a',
u'address',
u'applet',
u'area',
u'article',
u'aside',
u'b',
u'base',
u'basefont',
u'bgsound',
u'big',
u'blockquote',
u'body',
u'br',
u'button',
u'caption',
u'center',
u'code',
u'col',
u'colgroup',
u'command',
u'dd',
u'details',
u'dir',
u'div',
u'dl',
u'dt',
u'em',
u'embed',
u'fieldset',
u'figure',
u'font',
u'footer',
u'form',
u'frame',
u'frameset',
u'h1',
u'h2',
u'h3',
u'h4',
u'h5',
u'h6',
u'head',
u'header',
u'hr',
u'html',
u'i',
u'iframe',
u'image',
u'img',
u'input',
u'isindex',
u'li',
u'link',
u'listing',
u'marquee',
u'menu',
u'meta',
u'nav',
u'nobr',
u'noembed',
u'noframes',
u'noscript',
u'object',
u'ol',
u'p',
u'param',
u'plaintext',
u'pre',
u's',
u'script',
u'section',
u'select',
u'small',
u'source',
u'strike',
u'strong',
u'style',
u'table',
u'tbody',
u'td',
u'textarea',
u'tfoot',
u'th',
u'thead',
u'title',
u'tr',
u'track',
u'tt',
u'u',
u'ul',
u'wbr',
u'xmp',
six.u('a'),
six.u('address'),
six.u('applet'),
six.u('area'),
six.u('article'),
six.u('aside'),
six.u('b'),
six.u('base'),
six.u('basefont'),
six.u('bgsound'),
six.u('big'),
six.u('blockquote'),
six.u('body'),
six.u('br'),
six.u('button'),
six.u('caption'),
six.u('center'),
six.u('code'),
six.u('col'),
six.u('colgroup'),
six.u('command'),
six.u('dd'),
six.u('details'),
six.u('dir'),
six.u('div'),
six.u('dl'),
six.u('dt'),
six.u('em'),
six.u('embed'),
six.u('fieldset'),
six.u('figure'),
six.u('font'),
six.u('footer'),
six.u('form'),
six.u('frame'),
six.u('frameset'),
six.u('h1'),
six.u('h2'),
six.u('h3'),
six.u('h4'),
six.u('h5'),
six.u('h6'),
six.u('head'),
six.u('header'),
six.u('hr'),
six.u('html'),
six.u('i'),
six.u('iframe'),
six.u('image'),
six.u('img'),
six.u('input'),
six.u('isindex'),
six.u('li'),
six.u('link'),
six.u('listing'),
six.u('marquee'),
six.u('menu'),
six.u('meta'),
six.u('nav'),
six.u('nobr'),
six.u('noembed'),
six.u('noframes'),
six.u('noscript'),
six.u('object'),
six.u('ol'),
six.u('p'),
six.u('param'),
six.u('plaintext'),
six.u('pre'),
six.u('s'),
six.u('script'),
six.u('section'),
six.u('select'),
six.u('small'),
six.u('source'),
six.u('strike'),
six.u('strong'),
six.u('style'),
six.u('table'),
six.u('tbody'),
six.u('td'),
six.u('textarea'),
six.u('tfoot'),
six.u('th'),
six.u('thead'),
six.u('title'),
six.u('tr'),
six.u('track'),
six.u('tt'),
six.u('u'),
six.u('ul'),
six.u('wbr'),
six.u('xmp'),
]
37 changes: 19 additions & 18 deletions cottonmouth/html.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import collections
import six
from six.moves.collections_abc import Iterable
import itertools

from . import constants
Expand All @@ -8,7 +9,7 @@ def render(*content, **context):
"""
Renders a sequence of content as HTML.
"""
return u''.join((e for c in content for e in render_content(c, **context)))
return six.u('').join(e for c in content for e in render_content(c, **context))


def render_content(content, **context):
Expand All @@ -23,17 +24,17 @@ def render_content(content, **context):
- Any other value, coerced to unicode
"""
if content is None:
yield u''
elif isinstance(content, basestring):
yield six.u('')
elif isinstance(content, six.string_types):
yield content
elif callable(content):
for e in render_content(content(**context), **context):
yield e
elif isinstance(content, collections.Iterable):
elif isinstance(content, Iterable):
for e in render_iterable(content, **context):
yield e
else:
yield unicode(content)
yield six.text_type(content)


def render_iterable(content, **context):
Expand All @@ -44,11 +45,11 @@ def render_iterable(content, **context):
head = next(tail)

# Render tag around the content
if isinstance(head, basestring):
if isinstance(head, six.string_types):
for e in render_tag(head, tail, **context):
yield e
# Render nested lists
elif isinstance(head, collections.Iterable):
elif isinstance(head, Iterable):
for e in render_iterable(head, **context):
yield e
for content in tail:
Expand All @@ -72,36 +73,36 @@ def render_tag(tag, content, **context):
extra, remainder = {}, content

# Default to div if no explicit tag is provided
if tag.startswith(u'#'):
tag = u'div{}'.format(tag)
elif tag.startswith(u'.'):
tag = u'div{}'.format(tag)
if tag.startswith(six.u('#')):
tag = six.u('div{}').format(tag)
elif tag.startswith(six.u('.')):
tag = six.u('div{}').format(tag)

# Split tag into ["tag#id", "class1", "class2", ...] chunks
chunks = tag.split('.')

# Parse tag and id out of tag shortcut
tag = chunks[0]
if u'#' in chunks[0]:
if six.u('#') in chunks[0]:
tag, extra['id'] = chunks[0].split('#')

# Parse classes
classes = chunks[1:]
extra_classes = extra.get('class')
if isinstance(extra_classes, basestring):
if isinstance(extra_classes, six.string_types):
classes.extend(extra_classes.split())
elif extra_classes:
classes.extend(extra_classes)

# Format classes
if classes:
extra['class'] = u' '.join(classes)
extra['class'] = six.u(' ').join(classes)

# Format attributes
attributes = u''.join([u' {}="{}"'.format(*i) for i in extra.items()])
attributes = six.u('').join([six.u(' {}="{}"').format(*i) for i in extra.items()])

# Start our tag sandwich
yield u'<{}{}>'.format(tag, attributes)
yield six.u('<{}{}>').format(tag, attributes)

# Render the delicious filling or toppings
for content in remainder:
Expand All @@ -110,4 +111,4 @@ def render_tag(tag, content, **context):

# CLOSE THE TAG IF WE HAVE TO I GUESS
if tag not in constants.HTML_VOID_TAGS:
yield u'</{}>'.format(tag)
yield six.u('</{}>').format(tag)
5 changes: 3 additions & 2 deletions cottonmouth/tags.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import six
from . import constants


class Tag(unicode):
class Tag(six.text_type):
def __call__(self, *content, **extra):
tag = [unicode(self), extra]
tag = [six.text_type(self), extra]
tag.extend(content)
yield tag

Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@
url='https://github.com/nosamanuel/cottonmouth',
license=license,
packages=find_packages(exclude=('tests', 'docs')),
install_requires=['six'],
test_suite='tests',
)
Loading

0 comments on commit e83ee53

Please sign in to comment.