Hello World!
Lorem ipsum ...
| One | Two | Three |
pax_global_header 0000666 0000000 0000000 00000000064 13016466502 0014515 g ustar 00root root 0000000 0000000 52 comment=04541ec19fc4ab4e858f60a0fd2b5655f469c5a3
dominate-2.3.1/ 0000775 0000000 0000000 00000000000 13016466502 0013320 5 ustar 00root root 0000000 0000000 dominate-2.3.1/.gitignore 0000664 0000000 0000000 00000000541 13016466502 0015310 0 ustar 00root root 0000000 0000000 *.py[cod]
# C extensions
*.so
# Packages
*.egg
*.egg-info
dist
build
eggs
parts
bin
var
sdist
develop-eggs
.installed.cfg
lib
lib64
__pycache__
# Installer logs
pip-log.txt
# Unit test / coverage reports
.coverage
.tox
nosetests.xml
# Translations
*.mo
# Mr Developer
.mr.developer.cfg
.project
.pydevproject
*.sublime-workspace
*.sublime-project
dominate-2.3.1/.travis.yml 0000664 0000000 0000000 00000001036 13016466502 0015431 0 ustar 00root root 0000000 0000000 language: python
python:
- "2.7"
- "3.3"
- "3.4"
- "3.5"
- "pypy"
- "pypy3"
# command to install dependencies, e.g. pip install -r requirements.txt --use-mirrors
install:
- pip install pytest>=2.7.3 --upgrade
# command to run tests, e.g. python setup.py test
script:
- python setup.py sdist --format=zip
- pip install dist/dominate*.zip
- py.test
after_success:
- pip install coveralls coverage
- PYTHONPATH=. coverage run --source=dominate -m pytest
- coverage report
- coveralls
sudo: false
dominate-2.3.1/LICENSE.txt 0000664 0000000 0000000 00000016725 13016466502 0015156 0 ustar 00root root 0000000 0000000 GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
Lorem ipsum..
Test
Test
Lorem ipsum ...
| One | Two | Three |
Hello, Bob
Hello Bob
Hello Bob
This is a paragraph.
``` dominate-2.3.1/dominate/ 0000775 0000000 0000000 00000000000 13016466502 0015120 5 ustar 00root root 0000000 0000000 dominate-2.3.1/dominate/__init__.py 0000664 0000000 0000000 00000000130 13016466502 0017223 0 ustar 00root root 0000000 0000000 from ._version import __version__ version = __version__ from .document import document dominate-2.3.1/dominate/_version.py 0000664 0000000 0000000 00000000027 13016466502 0017315 0 ustar 00root root 0000000 0000000 __version__ = '2.3.1' dominate-2.3.1/dominate/document.py 0000664 0000000 0000000 00000004251 13016466502 0017312 0 ustar 00root root 0000000 0000000 __license__ = ''' This file is part of Dominate. Dominate is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Dominate is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Dominate. If not, see)
# otherwise, text will be escaped() and whitespace may be
# modified
is_inline = False
frame = namedtuple('frame', ['tag', 'items', 'used'])
def __new__(_cls, *args, **kwargs):
'''
Check if bare tag is being used a a decorator.
decorate the function and return
'''
if len(args) == 1 and isinstance(args[0], Callable) \
and not isinstance(args[0], dom_tag) and not kwargs:
wrapped = args[0]
@wraps(wrapped)
def f(*args, **kwargs):
with _cls() as _tag:
return wrapped(*args, **kwargs) or _tag
return f
return object.__new__(_cls)
def __init__(self, *args, **kwargs):
'''
Creates a new tag. Child tags should be passed as aruguments and attributes
should be passed as keyword arguments.
There is a non-rendering attribute which controls how the tag renders:
* `__inline` - Boolean value. If True renders all children tags on the same
line.
'''
self.attributes = {}
self.children = []
self.parent = None
self.document = None
# Does not insert newlines on all children if True (recursive attribute)
self.is_inline = kwargs.pop('__inline', self.is_inline)
self.is_pretty = kwargs.pop('__pretty', self.is_pretty)
#Add child elements
if args:
self.add(*args)
for attr, value in kwargs.items():
self.set_attribute(*dom_tag.clean_pair(attr, value))
self._ctx = None
self._add_to_ctx()
def _add_to_ctx(self):
ctx = dom_tag._with_contexts[_get_thread_context()]
if ctx and ctx[-1]:
self._ctx = ctx[-1]
ctx[-1].items.append(self)
# stack of (root_tag, [new_tags], set(used_tags))
_with_contexts = defaultdict(list)
def __enter__(self):
ctx = dom_tag._with_contexts[_get_thread_context()]
ctx.append(dom_tag.frame(self, [], set()))
return self
def __exit__(self, type, value, traceback):
ctx = dom_tag._with_contexts[_get_thread_context()]
slf, items, used = ctx[-1]
ctx[-1] = None
for item in items:
if item in used: continue
self.add(item)
ctx.pop()
def __call__(self, func):
'''
tag instance is being used as a decorator.
wrap func to make a copy of this tag
'''
# remove decorator from its context so it doesn't
# get added in where it was defined
if self._ctx:
self._ctx.used.add(self)
@wraps(func)
def f(*args, **kwargs):
tag = copy.deepcopy(self)
tag._add_to_ctx()
with tag:
return func(*args, **kwargs) or tag
return f
def set_attribute(self, key, value):
'''
Add or update the value of an attribute.
'''
if isinstance(key, int):
self.children[key] = value
elif isinstance(key, basestring):
self.attributes[key] = value
else:
raise TypeError('Only integer and string types are valid for assigning '
'child tags and attributes, respectively.')
__setitem__ = set_attribute
def delete_attribute(self, key):
if isinstance(key, int):
del self.children[key:key+1]
else:
del self.attributes[key]
__delitem__ = delete_attribute
def setdocument(self, doc):
'''
Creates a reference to the parent document to allow for partial-tree
validation.
'''
# assume that a document is correct in the subtree
if self.document != doc:
self.document = doc
for i in self.children:
if not isinstance(i, dom_tag): return
i.setdocument(doc)
def add(self, *args):
'''
Add new child tags.
'''
for obj in args:
if isinstance(obj, numbers.Number):
# Convert to string so we fall into next if block
obj = str(obj)
if isinstance(obj, basestring):
obj = escape(obj)
self.children.append(obj)
elif isinstance(obj, dom_tag):
ctx = dom_tag._with_contexts[_get_thread_context()]
if ctx and ctx[-1]:
ctx[-1].used.add(obj)
self.children.append(obj)
obj.parent = self
obj.setdocument(self.document)
elif isinstance(obj, dict):
for attr, value in obj.items():
self.set_attribute(*dom_tag.clean_pair(attr, value))
elif hasattr(obj, '__iter__'):
for subobj in obj:
self.add(subobj)
else: # wtf is it?
raise ValueError('%r not a tag or string.' % obj)
if len(args) == 1:
return args[0]
return args
def add_raw_string(self, s):
self.children.append(s)
def remove(self, obj):
self.children.remove(obj)
def clear(self):
for i in self.children:
if isinstance(i, dom_tag) and i.parent is self:
i.parent = None
self.children = []
def get(self, tag=None, **kwargs):
'''
Recursively searches children for tags of a certain
type with matching attributes.
'''
# Stupid workaround since we can not use dom_tag in the method declaration
if tag is None: tag = dom_tag
attrs = [(dom_tag.clean_attribute(attr), value)
for attr, value in kwargs.items()]
results = []
for child in self.children:
if (isinstance(tag, basestring) and type(child).__name__ == tag) or \
(not isinstance(tag, basestring) and isinstance(child, tag)):
if all(child.attributes.get(attribute) == value
for attribute, value in attrs):
# If the child is of correct type and has all attributes and values
# in kwargs add as a result
results.append(child)
if isinstance(child, dom_tag):
# If the child is a dom_tag extend the search down through its children
results.extend(child.get(tag, **kwargs))
return results
def __getitem__(self, key):
'''
Returns the stored value of the specified attribute or child
(if it exists).
'''
if isinstance(key, int):
# Children are accessed using integers
try:
return object.__getattribute__(self, 'children')[key]
except KeyError:
raise IndexError('Child with index "%s" does not exist.' % key)
elif isinstance(key, basestring):
# Attributes are accessed using strings
try:
return object.__getattribute__(self, 'attributes')[key]
except KeyError:
raise AttributeError('Attribute "%s" does not exist.' % key)
else:
raise TypeError('Only integer and string types are valid for accessing '
'child tags and attributes, respectively.')
__getattr__ = __getitem__
def __len__(self):
'''
Number of child elements.
'''
return len(self.children)
def __bool__(self):
'''
Hack for "if x" and __len__
'''
return True
__nonzero__ = __bool__
def __iter__(self):
'''
Iterates over child elements.
'''
return self.children.__iter__()
def __contains__(self, item):
'''
Checks recursively if item is in children tree.
Accepts both a string and a class.
'''
return bool(self.get(item))
def __iadd__(self, obj):
'''
Reflexive binary addition simply adds tag as a child.
'''
self.add(obj)
return self
# String and unicode representations are the same as render()
def __unicode__(self):
return self.render()
__str__ = __unicode__
def render(self, indent=' ', pretty=True, xhtml=False):
data = self._render([], 0, indent, pretty, xhtml)
return u''.join(data)
def _render(self, sb, indent_level, indent_str, pretty, xhtml):
pretty = pretty and self.is_pretty
t = type(self)
name = getattr(t, 'tagname', t.__name__)
# Workaround for python keywords and standard classes/methods
# (del, object, input)
if name[-1] == '_':
name = name[:-1]
# open tag
sb.append('<')
sb.append(name)
for attribute, value in sorted(self.attributes.items()):
sb.append(' %s="%s"' % (attribute, escape(unicode(value), True)))
sb.append(' />' if self.is_single and xhtml else '>')
if not self.is_single:
inline = self._render_children(sb, indent_level + 1, indent_str, pretty, xhtml)
if pretty and not inline:
sb.append('\n')
sb.append(indent_str * indent_level)
# close tag
sb.append('')
sb.append(name)
sb.append('>')
return sb
def _render_children(self, sb, indent_level, indent_str, pretty, xhtml):
inline = True
for child in self.children:
if isinstance(child, dom_tag):
if pretty and not child.is_inline:
inline = False
sb.append('\n')
sb.append(indent_str * indent_level)
child._render(sb, indent_level, indent_str, pretty, xhtml)
else:
sb.append(unicode(child))
return inline
def __repr__(self):
name = '%s.%s' % (self.__module__, type(self).__name__)
attributes_len = len(self.attributes)
attributes = '%s attribute' % attributes_len
if attributes_len != 1: attributes += 's'
children_len = len(self.children)
children = '%s child' % children_len
if children_len != 1: children += 'ren'
return '<%s at %x: %s, %s>' % (name, id(self), attributes, children)
@staticmethod
def clean_attribute(attribute):
'''
Since some attributes match python keywords we prepend them with
underscores. Python also does not support colons in keywords so underscores
mid-attribute are replaced with colons.
'''
# shorthand
attribute = {
'cls': 'class',
'className': 'class',
'class_name': 'class',
'fr': 'for',
'html_for': 'for',
'htmlFor': 'for',
}.get(attribute, attribute)
# Workaround for python's reserved words
if attribute[0] == '_': attribute = attribute[1:]
# Workaround for inability to use colon in python keywords
if attribute in set(['http_equiv']) or attribute.startswith('data_'):
return attribute.replace('_', '-').lower()
return attribute.replace('_', ':').lower()
@classmethod
def clean_pair(cls, attribute, value):
'''
This will call `clean_attribute` on the attribute and also allows for the
creation of boolean attributes.
Ex. input(selected=True) is equivalent to input(selected="selected")
'''
attribute = cls.clean_attribute(attribute)
# Check for boolean attributes
# (i.e. selected=True becomes selected="selected")
if value is True:
value = attribute
if value is False:
value = "false"
return (attribute, value)
def attr(*args, **kwargs):
'''
Set attributes on the current active tag context
'''
ctx = dom_tag._with_contexts[_get_thread_context()]
if ctx and ctx[-1]:
dicts = args + (kwargs,)
for d in dicts:
for attr, value in d.items():
ctx[-1].tag.set_attribute(*dom_tag.clean_pair(attr, value))
else:
raise ValueError('not in a tag context')
# escape() is used in render
from .util import escape
dominate-2.3.1/dominate/tags.py 0000664 0000000 0000000 00000066626 13016466502 0016450 0 ustar 00root root 0000000 0000000 '''
HTML tag classes.
'''
__license__ = '''
This file is part of Dominate.
Dominate is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Dominate is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with Dominate. If not, see
.
'''
from .dom_tag import dom_tag, attr
from .dom1core import dom1core
try:
basestring = basestring
except NameError: # py3
basestring = str
unicode = str
underscored_classes = set(['del', 'input', 'map', 'object'])
# Tag attributes
_ATTR_GLOBAL = set([
'accesskey', 'class', 'class', 'contenteditable', 'contextmenu', 'dir',
'draggable', 'id', 'item', 'hidden', 'lang', 'itemprop', 'spellcheck',
'style', 'subject', 'tabindex', 'title'
])
_ATTR_EVENTS = set([
'onabort', 'onblur', 'oncanplay', 'oncanplaythrough', 'onchange', 'onclick',
'oncontextmenu', 'ondblclick', 'ondrag', 'ondragend', 'ondragenter',
'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'ondurationchange',
'onemptied', 'onended', 'onerror', 'onfocus', 'onformchange', 'onforminput',
'oninput', 'oninvalid', 'onkeydown', 'onkeypress', 'onkeyup', 'onload',
'onloadeddata', 'onloadedmetadata', 'onloadstart', 'onmousedown',
'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel',
'onpause', 'onplay', 'onplaying', 'onprogress', 'onratechange',
'onreadystatechange', 'onscroll', 'onseeked', 'onseeking', 'onselect',
'onshow', 'onstalled', 'onsubmit', 'onsuspend', 'ontimeupdate',
'onvolumechange', 'onwaiting'
])
ERR_ATTRIBUTE = 'attributes'
ERR_CONTEXT = 'context'
ERR_CONTENT = 'content'
class html_tag(dom_tag, dom1core):
def __init__(self, *args, **kwargs):
'''
Creates a new html tag instance.
'''
super(html_tag, self).__init__(*args, **kwargs)
# def validate(self):
# '''
# Validate the tag. This will check the attributes, context, and contents and
# emit tuples in the form of: element, message.
# '''
# errors = []
# errors.extend(self.validate_attributes())
# errors.extend(self.validate_context())
# errors.extend(self.validate_content())
# return errors
# def validate_attributes(self):
# '''
# Validate the tag attributes.
# '''
# return []
# def validate_context(self):
# '''
# Validate the tag context.
# '''
# return []
# def validate_content(self):
# '''
# Validate the content of the tag.
# '''
# return []
# def _check_attributes(self, *attrs):
# valid = set([])
# for attr in attrs:
# if hasattr(attr, '__iter__'):
# valid |= set(attr)
# else:
# valid.add(attr)
# return set(list(self.attributes.iterkeys())) - valid
################################################################################
############################### Html Tag Classes ###############################
################################################################################
# Root element
class html(html_tag):
'''
The html element represents the root of an HTML document.
'''
pass
# def validate_attributes(self):
# errors = []
# for invalid in self._check_attributes(_ATTR_GLOBAL, 'manifest'):
# errors.append( (self, ERR_ATTRIBUTE, 'Invalid attribute: "%s"' % invalid) )
# return errors
# def validate_context(self):
# if self.parent is not None and not isinstance(self.parent, iframe):
# return [(self, ERR_CONTEXT, 'Must be root element or child of an