Hello World!
Lorem ipsum ...
| One | Two | Three |
pax_global_header 0000666 0000000 0000000 00000000064 14542114066 0014515 g ustar 00root root 0000000 0000000 52 comment=9176ade46164585bdc7c603a957e3b52684dc9e7
dominate-2.9.1/ 0000775 0000000 0000000 00000000000 14542114066 0013326 5 ustar 00root root 0000000 0000000 dominate-2.9.1/.github/ 0000775 0000000 0000000 00000000000 14542114066 0014666 5 ustar 00root root 0000000 0000000 dominate-2.9.1/.github/workflows/ 0000775 0000000 0000000 00000000000 14542114066 0016723 5 ustar 00root root 0000000 0000000 dominate-2.9.1/.github/workflows/.coveragerc 0000664 0000000 0000000 00000000034 14542114066 0021041 0 ustar 00root root 0000000 0000000 [run]
relative_files = True
dominate-2.9.1/.github/workflows/ci.yml 0000664 0000000 0000000 00000004045 14542114066 0020044 0 ustar 00root root 0000000 0000000 # This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
name: Dominate
on:
push:
branches: ["master"]
pull_request:
branches: ["master"]
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
python: ["3"]
os: ["ubuntu-latest"]
include:
- {python: "3.7", os: "ubuntu-22.04"}
- {python: "3.8", os: "ubuntu-22.04"}
- {python: "3.9", os: "ubuntu-22.04"}
- {python: "3.10", os: "ubuntu-22.04"}
- {python: "3.11", os: "ubuntu-22.04"}
- {python: "3.12", os: "ubuntu-22.04"}
steps:
- uses: actions/checkout@v3
- name: "Set up Python ${{ matrix.python }}"
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python }}
- name: "Install dependencies"
run: |
# python -m pip install --upgrade pip
python -m pip install pytest
python -m pip install mock
python -m pip install flake8
python -m pip install importlib_metadata
python -m pip install "setuptools>=62"
python -m pip install wheel
python -m pip install build
- name: "Lint with flake8"
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=80 --statistics
- name: "Build and test"
run: |
python -m build --no-isolation
pip install dist/dominate*.tar.gz
pytest
- name: Coveralls
env:
COVERAGE_RCFILE: ".github/workflows/.coveragerc"
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
python -m pip install coverage
python -m pip install coveralls
coverage run --source=dominate -m pytest
python -m coveralls --service=github || true
dominate-2.9.1/.gitignore 0000664 0000000 0000000 00000000575 14542114066 0015325 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
.idea
.idea/
.venv/
.envrc
dominate-2.9.1/LICENSE.txt 0000664 0000000 0000000 00000016725 14542114066 0015164 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 |
Have a look at our other products
``` Decorators ---------- `Dominate` is great for creating reusable widgets for parts of your page. Consider this example: ```python def greeting(name): with div() as d: p('Hello, %s' % name) return d print(greeting('Bob')) ``` ```htmlHello, Bob
Hello Bob
Hello Bob
This is a paragraph.
``` Embedding HTML -------------- If you need to embed a node of pre-formed HTML coming from a library such as markdown or the like, you can avoid escaped HTML by using the raw method from the dominate.util package: ``` from dominate.util import raw ... td(raw('Example')) ``` Without the raw call, this code would render escaped HTML with lt, etc. SVG --- The `dominate.svg` module contains SVG tags similar to how `dominate.tags` contains HTML tags. SVG elements will automatically convert `_` to `-` for dashed elements. For example: ```python from dominate.svg import * print(circle(stroke_width=5)) ``` ```html)
# otherwise, text will be escaped() and whitespace may be
# modified
is_inline = False
def __new__(_cls, *args, **kwargs):
'''
Check if bare tag is being used a a decorator
(called with a single function arg).
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 arguments 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
# 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(*type(self).clean_pair(attr, value))
self._ctx = None
self._add_to_ctx()
# context manager
frame = namedtuple('frame', ['tag', 'items', 'used'])
# stack of frames
_with_contexts = defaultdict(list)
def _add_to_ctx(self):
stack = dom_tag._with_contexts.get(_get_thread_context())
if stack:
self._ctx = stack[-1]
stack[-1].items.append(self)
def __enter__(self):
stack = dom_tag._with_contexts[_get_thread_context()]
stack.append(dom_tag.frame(self, [], set()))
return self
def __exit__(self, type, value, traceback):
thread_id = _get_thread_context()
stack = dom_tag._with_contexts[thread_id]
frame = stack.pop()
for item in frame.items:
if item in frame.used: continue
self.add(item)
if not stack:
del dom_tag._with_contexts[thread_id]
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 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 = util.escape(obj)
self.children.append(obj)
elif isinstance(obj, dom_tag):
stack = dom_tag._with_contexts.get(_get_thread_context(), [])
for s in stack:
s.used.add(obj)
self.children.append(obj)
obj.parent = self
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 IndexError:
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
name = getattr(self, 'tagname', type(self).__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()):
if value in (False, None):
continue
val = unicode(value) if isinstance(value, util.text) and not value.escape else util.escape(unicode(value), True)
sb.append(' %s="%s"' % (attribute, val))
sb.append(' />' if self.is_single and xhtml else '>')
if self.is_single:
return sb
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):
'''
Normalize attribute names for shorthand and work arounds for limitations
in Python's syntax
'''
# Shorthand
attribute = {
'cls': 'class',
'className': 'class',
'class_name': 'class',
'klass': 'class',
'fr': 'for',
'html_for': 'for',
'htmlFor': 'for',
'phor': 'for',
}.get(attribute, attribute)
# Workaround for Python's reserved words
if attribute[0] == '_':
attribute = attribute[1:]
# Workaround for dash
special_prefix = any([attribute.startswith(x) for x in ('data_', 'aria_')])
if attribute in set(['http_equiv']) or special_prefix:
attribute = attribute.replace('_', '-').lower()
# Workaround for colon
if attribute.split('_')[0] in ('xlink', 'xml', 'xmlns'):
attribute = attribute.replace('_', ':', 1).lower()
return attribute
@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
# Ignore `if value is False`: this is filtered out in render()
return (attribute, value)
_get_current_none = object()
def get_current(default=_get_current_none):
'''
get the current tag being used as a with context or decorated function.
if no context is active, raises ValueError, or returns the default, if provided
'''
h = _get_thread_context()
ctx = dom_tag._with_contexts.get(h, None)
if ctx:
return ctx[-1].tag
if default is _get_current_none:
raise ValueError('no current context')
return default
def attr(*args, **kwargs):
'''
Set attributes on the current active tag context
'''
c = get_current()
dicts = args + (kwargs,)
for d in dicts:
for attr, value in d.items():
c.set_attribute(*dom_tag.clean_pair(attr, value))
from . import util
dominate-2.9.1/dominate/svg.py 0000664 0000000 0000000 00000021641 14542114066 0016303 0 ustar 00root root 0000000 0000000 '''
This module consists of classes specific to HTML5-SVG Elements. In general this module does not include
- Elements that are not specific to SVG (eg. )
- Elements that are deprecated
'''
from dominate.tags import html_tag
from dominate.dom_tag import dom_tag
import numbers
__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
.
'''
# Tag attributes
_ATTR_GLOBAL = set([
'accesskey', 'class', 'class', 'contenteditable', 'contextmenu', 'dir',
'draggable', 'id', 'item', 'hidden', 'lang', 'itemprop', 'spellcheck',
'style', 'subject', 'tabindex', 'title'
])
# https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/Events#Attributes
_ATTR_EVENTS = set([
'onbegin', 'onend', 'onrepeat',
'onabort', 'onerror', 'onresize', 'onscroll', 'onunload',
'oncopy', 'oncut', 'onpaste',
'oncancel', 'oncanplay', 'oncanplaythrough', 'onchange', 'onclick', 'onclose', 'oncuechange', 'ondblclick',
'ondrag', 'ondragend', 'ondragenter', 'ondragexit', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop',
'ondurationchange', 'onemptied', 'onended', 'onerror', 'onfocus', 'oninput', 'oninvalid', 'onkeydown', 'onkeypress',
'onkeyup', 'onload', 'onloadeddata', 'onloadedmetadata','onloadstart', 'onmousedown', 'onmouseenter',
'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onpause', 'onplay',
'onplaying', 'onprogress', 'onratechange', 'onreset', 'onresize', 'onscroll', 'onseeked', 'onseeking', 'onselect',
'onshow', 'onstalled', 'onsubmit', 'onsuspend', 'ontimeupdate', 'ontoggle', 'onvolumechange', 'onwaiting'
])
DASHED_ATTRIBUTES = set([
'accent', 'alignment', 'arabic', 'baseline', 'cap', 'clip', 'color', 'dominant', 'enable', 'fill', 'flood',
'font', 'glyph', 'horiz', 'image', 'letter', 'lighting', 'marker', 'overline', 'paint', 'panose', 'pointer',
'rendering', 'shape', 'stop', 'strikethrough', 'stroke', 'text', 'underline', 'unicode', 'units', 'v', 'vector',
'vert', 'word', 'writing', 'x'
])
# https://developer.mozilla.org/en-US/docs/Web/SVG/Element/svg
class svg_tag(html_tag):
@staticmethod
def clean_attribute(attribute):
attribute = html_tag.clean_attribute(attribute)
words = attribute.split('_')
if words[0] in DASHED_ATTRIBUTES:
return attribute.replace('_', '-')
return attribute
class svg(svg_tag):
pass
class animate(svg_tag):
'''
The animate SVG element is used to animate an attribute or property of an element over time.
It's normally inserted inside the element or referenced by the href attribute of the target element.
'''
pass
class animateMotion(svg_tag):
'''
The element causes a referenced element to move along a motion path.
'''
pass
class animateTransform(svg_tag):
'''
The animateTransform element animates a transformation attribute on its target element, thereby allowing
animations to control translation, scaling, rotation, and/or skewing.
'''
is_single = True
class circle(svg_tag):
'''
The SVG element is an SVG basic shape, used to draw circles based on a center point and a radius.
'''
pass
class clipPath(svg_tag):
'''
The SVG element defines a clipping path, to be used used by the clip-path property.
'''
pass
class defs(svg_tag):
'''
The element is used to store graphical objects that will be used at a later time. Objects created inside a
element are not rendered directly. To display them you have to reference them
(with a