asd
This commit is contained in:
4
venv/lib/python3.12/site-packages/dominate/__init__.py
Normal file
4
venv/lib/python3.12/site-packages/dominate/__init__.py
Normal file
@ -0,0 +1,4 @@
|
||||
from ._version import __version__
|
||||
version = __version__
|
||||
|
||||
from .document import document
|
1
venv/lib/python3.12/site-packages/dominate/_version.py
Normal file
1
venv/lib/python3.12/site-packages/dominate/_version.py
Normal file
@ -0,0 +1 @@
|
||||
__version__ = '2.9.1'
|
76
venv/lib/python3.12/site-packages/dominate/document.py
Normal file
76
venv/lib/python3.12/site-packages/dominate/document.py
Normal file
@ -0,0 +1,76 @@
|
||||
__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
|
||||
<http://www.gnu.org/licenses/>.
|
||||
'''
|
||||
|
||||
from . import tags
|
||||
from . import util
|
||||
|
||||
try:
|
||||
basestring = basestring
|
||||
except NameError: # py3
|
||||
basestring = str
|
||||
unicode = str
|
||||
|
||||
class document(tags.html):
|
||||
tagname = 'html'
|
||||
def __init__(self, title='Dominate', doctype='<!DOCTYPE html>', *a, **kw):
|
||||
'''
|
||||
Creates a new document instance. Accepts `title` and `doctype`
|
||||
'''
|
||||
super(document, self).__init__(*a, **kw)
|
||||
self.doctype = doctype
|
||||
self.head = super(document, self).add(tags.head())
|
||||
self.body = super(document, self).add(tags.body())
|
||||
if title is not None:
|
||||
self.title_node = self.head.add(tags.title(title))
|
||||
with self.body:
|
||||
self.header = util.container()
|
||||
self.main = util.container()
|
||||
self.footer = util.container()
|
||||
self._entry = self.main
|
||||
|
||||
def get_title(self):
|
||||
return self.title_node.text
|
||||
|
||||
def set_title(self, title):
|
||||
if isinstance(title, basestring):
|
||||
self.title_node.text = title
|
||||
else:
|
||||
self.head.remove(self.title_node)
|
||||
self.head.add(title)
|
||||
self.title_node = title
|
||||
|
||||
title = property(get_title, set_title)
|
||||
|
||||
def add(self, *args):
|
||||
'''
|
||||
Adding tags to a document appends them to the <body>.
|
||||
'''
|
||||
return self._entry.add(*args)
|
||||
|
||||
def _render(self, sb, *args, **kwargs):
|
||||
'''
|
||||
Renders the DOCTYPE and tag tree.
|
||||
'''
|
||||
# adds the doctype if one was set
|
||||
if self.doctype:
|
||||
sb.append(self.doctype)
|
||||
sb.append('\n')
|
||||
return super(document, self)._render(sb, *args, **kwargs)
|
||||
|
||||
def __repr__(self):
|
||||
return '<dominate.document "%s">' % self.title
|
64
venv/lib/python3.12/site-packages/dominate/dom1core.py
Normal file
64
venv/lib/python3.12/site-packages/dominate/dom1core.py
Normal file
@ -0,0 +1,64 @@
|
||||
__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
|
||||
<http://www.gnu.org/licenses/>.
|
||||
'''
|
||||
|
||||
try:
|
||||
basestring = basestring
|
||||
except NameError: # py3
|
||||
basestring = str
|
||||
unicode = str
|
||||
|
||||
|
||||
class dom1core(object):
|
||||
'''
|
||||
Implements the Document Object Model (Core) Level 1
|
||||
|
||||
http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/
|
||||
http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html
|
||||
'''
|
||||
@property
|
||||
def parentNode(self):
|
||||
'''
|
||||
DOM API: Returns the parent tag of the current element.
|
||||
'''
|
||||
return self.parent
|
||||
|
||||
def getElementById(self, id):
|
||||
'''
|
||||
DOM API: Returns single element with matching id value.
|
||||
'''
|
||||
results = self.get(id=id)
|
||||
if len(results) > 1:
|
||||
raise ValueError('Multiple tags with id "%s".' % id)
|
||||
elif results:
|
||||
return results[0]
|
||||
return None
|
||||
|
||||
def getElementsByTagName(self, name):
|
||||
'''
|
||||
DOM API: Returns all tags that match name.
|
||||
'''
|
||||
if isinstance(name, basestring):
|
||||
return self.get(name.lower())
|
||||
return None
|
||||
|
||||
def appendChild(self, obj):
|
||||
'''
|
||||
DOM API: Add an item to the end of the children list.
|
||||
'''
|
||||
self.add(obj)
|
||||
return self
|
505
venv/lib/python3.12/site-packages/dominate/dom_tag.py
Normal file
505
venv/lib/python3.12/site-packages/dominate/dom_tag.py
Normal file
@ -0,0 +1,505 @@
|
||||
__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
|
||||
<http://www.gnu.org/licenses/>.
|
||||
'''
|
||||
|
||||
# pylint: disable=bad-indentation, bad-whitespace, missing-docstring
|
||||
|
||||
import copy
|
||||
import numbers
|
||||
from collections import defaultdict, namedtuple
|
||||
from functools import wraps
|
||||
import threading
|
||||
from asyncio import get_event_loop
|
||||
from uuid import uuid4
|
||||
from contextvars import ContextVar
|
||||
|
||||
try:
|
||||
# Python 3
|
||||
from collections.abc import Callable
|
||||
except ImportError: # pragma: no cover
|
||||
# Python 2.7
|
||||
from collections import Callable
|
||||
|
||||
try:
|
||||
basestring = basestring
|
||||
except NameError: # py3 # pragma: no cover
|
||||
basestring = str
|
||||
unicode = str
|
||||
|
||||
try:
|
||||
import greenlet
|
||||
except ImportError:
|
||||
greenlet = None
|
||||
|
||||
# We want dominate to work in async contexts - however, the problem is
|
||||
# when we bind a tag using "with", we set what is essentially a global variable.
|
||||
# If we are processing multiple documents at the same time, one context
|
||||
# can "overwrite" the "bound tag" of another - this can cause documents to
|
||||
# sort of bleed into one another...
|
||||
|
||||
# The solution is to use a ContextVar - which provides async context local storage.
|
||||
# We use this to store a unique ID for each async context. We then use thie ID to
|
||||
# form the key (in _get_thread_context) that is used to index the _with_context defaultdict.
|
||||
# The presense of this key ensures that each async context has its own stack and doesn't conflict.
|
||||
async_context_id = ContextVar('async_context_id', default = None)
|
||||
|
||||
def _get_async_context_id():
|
||||
if async_context_id.get() is None:
|
||||
async_context_id.set(uuid4().hex)
|
||||
return async_context_id.get()
|
||||
|
||||
def _get_thread_context():
|
||||
context = [threading.current_thread()]
|
||||
# Tag extra content information with a name to make sure
|
||||
# a greenlet.getcurrent() == 1 doesn't get confused with a
|
||||
# a _get_thread_context() == 1.
|
||||
if greenlet:
|
||||
context.append(("greenlet", greenlet.getcurrent()))
|
||||
|
||||
try:
|
||||
if get_event_loop().is_running():
|
||||
# Only add this extra information if we are actually in a running event loop
|
||||
context.append(("async", _get_async_context_id()))
|
||||
# A runtime error is raised if there is no async loop...
|
||||
except RuntimeError:
|
||||
pass
|
||||
return tuple(context)
|
||||
|
||||
class dom_tag(object):
|
||||
is_single = False # Tag does not require matching end tag (ex. <hr/>)
|
||||
is_pretty = True # Text inside the tag should be left as-is (ex. <pre>)
|
||||
# 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
|
362
venv/lib/python3.12/site-packages/dominate/svg.py
Normal file
362
venv/lib/python3.12/site-packages/dominate/svg.py
Normal file
@ -0,0 +1,362 @@
|
||||
'''
|
||||
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. <a>)
|
||||
- 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
|
||||
<http://www.gnu.org/licenses/>.
|
||||
'''
|
||||
|
||||
# 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 <animateMotion> 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 <circle> 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 <clipPath> SVG element defines a clipping path, to be used used by the clip-path property.
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class defs(svg_tag):
|
||||
'''
|
||||
The <defs> element is used to store graphical objects that will be used at a later time. Objects created inside a
|
||||
<defs> element are not rendered directly. To display them you have to reference them
|
||||
(with a <use> element for example).
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class desc(svg_tag):
|
||||
'''
|
||||
The <desc> element provides an accessible, long-text description of any SVG container element or graphics element.
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class ellipse(svg_tag):
|
||||
'''
|
||||
An ellipse element for svg containers
|
||||
'''
|
||||
pass
|
||||
|
||||
# (Note, filters are at the bottom of this file)
|
||||
|
||||
class g(svg_tag):
|
||||
'''
|
||||
The <g> SVG element is a container used to group other SVG elements.
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class image(svg_tag):
|
||||
'''
|
||||
The <image> SVG element includes images inside SVG documents. It can display raster image files or other SVG files.
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class line(svg_tag):
|
||||
'''
|
||||
The <line> element is an SVG basic shape used to create a line connecting two points.
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class linearGradient(svg_tag):
|
||||
'''
|
||||
The <linearGradient> element lets authors define linear gradients that can be applied to fill or
|
||||
stroke of graphical elements.
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class marker(svg_tag):
|
||||
'''
|
||||
The <marker> element defines the graphic that is to be used for drawing arrowheads or polymarkers on a given <path>, <line>, <polyline> or <polygon> element.
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class mask(svg_tag):
|
||||
'''
|
||||
The <mask> element defines an alpha mask for compositing the current object into the background.
|
||||
A mask is used/referenced using the mask property.
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class mpath(svg_tag):
|
||||
'''
|
||||
The <mpath> sub-element for the <animateMotion> element provides the ability to reference an
|
||||
external <path> element as the definition of a motion path.
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class pattern(svg_tag):
|
||||
'''
|
||||
The <pattern> element defines a graphics object which can be redrawn at repeated x and y-coordinate
|
||||
intervals ("tiled") to cover an area.
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class polygon(svg_tag):
|
||||
'''
|
||||
A polygon element for svg containers
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class polyline(svg_tag):
|
||||
'''
|
||||
A polyline element for svg containers
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class radialGradient(svg_tag):
|
||||
'''
|
||||
The <radialGradient> element lets authors define radial gradients that can be applied to fill
|
||||
or stroke of graphical elements.
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class path(svg_tag):
|
||||
'''
|
||||
A path element for svg containers
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class rect(svg_tag):
|
||||
'''
|
||||
A rectangle element for svg containers
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class stop(svg_tag):
|
||||
'''
|
||||
The SVG <stop> element defines a color and its position to use on a gradient.
|
||||
This element is always a child of a <linearGradient> or <radialGradient> element.
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class switch(svg_tag):
|
||||
'''
|
||||
The <switch> SVG element evaluates any requiredFeatures, requiredExtensions and systemLanguage attributes
|
||||
on its direct child elements in order, and then renders the first child where these attributes evaluate to true.
|
||||
Other direct children will be bypassed and therefore not rendered. If a child element is a container element,
|
||||
like <g>, then its subtree is also processed/rendered or bypassed/not rendered.
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class symbol(svg_tag):
|
||||
'''
|
||||
The use of symbol elements for graphics that are used multiple times in the same document adds structure and
|
||||
semantics. Documents that are rich in structure may be rendered graphically, as speech, or as Braille,
|
||||
and thus promote accessibility.
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class text(svg_tag):
|
||||
'''
|
||||
The SVG <text> element draws a graphics element consisting of text. It's possible to apply a gradient,
|
||||
pattern, clipping path, mask, or filter to <text>, like any other SVG graphics element.
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class textPath(svg_tag):
|
||||
'''
|
||||
To render text along the shape of a <path>, enclose the text in a <textPath> element that has an href
|
||||
attribute with a reference to the <path> element.
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class title(svg_tag):
|
||||
'''
|
||||
The <title> element provides an accessible, short-text description of any SVG container
|
||||
element or graphics element.
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class tspan(svg_tag):
|
||||
'''
|
||||
The SVG <tspan> element define a subtext within a <text> element or another <tspan> element.
|
||||
It allows to adjust the style and/or position of that subtext as needed.
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class use(svg_tag):
|
||||
'''
|
||||
The <use> element takes nodes from within the SVG document, and duplicates them somewhere else.
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class view(svg_tag):
|
||||
'''
|
||||
A view is a defined way to view the image, like a zoom level or a detail view.
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
# FILTERS
|
||||
class filter(svg_tag):
|
||||
pass
|
||||
|
||||
class feBlend(svg_tag):
|
||||
pass
|
||||
|
||||
class feColorMatrix(svg_tag):
|
||||
pass
|
||||
|
||||
class feComponentTransfer(svg_tag):
|
||||
pass
|
||||
|
||||
class feComposite(svg_tag):
|
||||
pass
|
||||
|
||||
class feConvolveMatrix(svg_tag):
|
||||
pass
|
||||
|
||||
class feDiffuseLighting(svg_tag):
|
||||
pass
|
||||
|
||||
class feDisplacementMap(svg_tag):
|
||||
pass
|
||||
|
||||
class feFlood(svg_tag):
|
||||
pass
|
||||
|
||||
class feGaussianBlur(svg_tag):
|
||||
pass
|
||||
|
||||
class feImage(svg_tag):
|
||||
pass
|
||||
|
||||
class feMerge(svg_tag):
|
||||
pass
|
||||
|
||||
class feMorphology(svg_tag):
|
||||
pass
|
||||
|
||||
class feOffset(svg_tag):
|
||||
pass
|
||||
|
||||
class feSpecularLighting(svg_tag):
|
||||
pass
|
||||
|
||||
class feTile(svg_tag):
|
||||
pass
|
||||
|
||||
class feTurbulence(svg_tag):
|
||||
pass
|
||||
|
||||
class feDistantLight(svg_tag):
|
||||
pass
|
||||
|
||||
class fePointLight(svg_tag):
|
||||
pass
|
||||
|
||||
class feSpotLight(svg_tag):
|
||||
pass
|
1131
venv/lib/python3.12/site-packages/dominate/tags.py
Normal file
1131
venv/lib/python3.12/site-packages/dominate/tags.py
Normal file
File diff suppressed because it is too large
Load Diff
186
venv/lib/python3.12/site-packages/dominate/util.py
Normal file
186
venv/lib/python3.12/site-packages/dominate/util.py
Normal file
@ -0,0 +1,186 @@
|
||||
'''
|
||||
Utility classes for creating dynamic html documents
|
||||
'''
|
||||
|
||||
__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
|
||||
<http://www.gnu.org/licenses/>.
|
||||
'''
|
||||
|
||||
import re
|
||||
|
||||
from .dom_tag import dom_tag
|
||||
|
||||
try:
|
||||
basestring = basestring
|
||||
except NameError:
|
||||
basestring = str
|
||||
unichr = chr
|
||||
|
||||
|
||||
def include(f):
|
||||
'''
|
||||
includes the contents of a file on disk.
|
||||
takes a filename
|
||||
'''
|
||||
fl = open(f, 'r')
|
||||
data = fl.read()
|
||||
fl.close()
|
||||
return raw(data)
|
||||
|
||||
|
||||
def system(cmd, data=None):
|
||||
'''
|
||||
pipes the output of a program
|
||||
'''
|
||||
import subprocess
|
||||
s = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
|
||||
out, err = s.communicate(data)
|
||||
return out.decode('utf8')
|
||||
|
||||
|
||||
def escape(data, quote=True): # stolen from std lib cgi
|
||||
'''
|
||||
Escapes special characters into their html entities
|
||||
Replace special characters "&", "<" and ">" to HTML-safe sequences.
|
||||
If the optional flag quote is true, the quotation mark character (")
|
||||
is also translated.
|
||||
|
||||
This is used to escape content that appears in the body of an HTML document
|
||||
'''
|
||||
data = data.replace("&", "&") # Must be done first!
|
||||
data = data.replace("<", "<")
|
||||
data = data.replace(">", ">")
|
||||
if quote:
|
||||
data = data.replace('"', """)
|
||||
return data
|
||||
|
||||
|
||||
_unescape = {
|
||||
'quot': 34,
|
||||
'amp': 38,
|
||||
'lt': 60,
|
||||
'gt': 62,
|
||||
'nbsp': 32,
|
||||
# more here
|
||||
# http://www.w3.org/TR/html4/sgml/entities.html
|
||||
'yuml': 255,
|
||||
}
|
||||
str_escape = escape
|
||||
|
||||
|
||||
def unescape(data):
|
||||
'''
|
||||
unescapes html entities. the opposite of escape.
|
||||
'''
|
||||
cc = re.compile(r'&(?:(?:#(\d+))|([^;]+));')
|
||||
|
||||
result = []
|
||||
m = cc.search(data)
|
||||
while m:
|
||||
result.append(data[0:m.start()])
|
||||
d = m.group(1)
|
||||
if d:
|
||||
d = int(d)
|
||||
result.append(unichr(d))
|
||||
else:
|
||||
d = _unescape.get(m.group(2), ord('?'))
|
||||
result.append(unichr(d))
|
||||
|
||||
data = data[m.end():]
|
||||
m = cc.search(data)
|
||||
|
||||
result.append(data)
|
||||
return ''.join(result)
|
||||
|
||||
|
||||
_reserved = ";/?:@&=+$, "
|
||||
_replace_map = dict((c, '%%%2X' % ord(c)) for c in _reserved)
|
||||
|
||||
|
||||
def url_escape(data):
|
||||
return ''.join(_replace_map.get(c, c) for c in data)
|
||||
|
||||
|
||||
def url_unescape(data):
|
||||
return re.sub('%([0-9a-fA-F]{2})',
|
||||
lambda m: unichr(int(m.group(1), 16)), data)
|
||||
|
||||
|
||||
class container(dom_tag):
|
||||
'''
|
||||
Contains multiple elements, but does not add a level
|
||||
'''
|
||||
is_inline = True
|
||||
def _render(self, sb, indent_level, indent_str, pretty, xhtml):
|
||||
inline = self._render_children(sb, indent_level, indent_str, pretty, xhtml)
|
||||
if pretty and not inline:
|
||||
sb.append('\n')
|
||||
sb.append(indent_str * (indent_level - 1))
|
||||
return sb
|
||||
|
||||
|
||||
class lazy(dom_tag):
|
||||
'''
|
||||
delays function execution until rendered
|
||||
'''
|
||||
def __new__(_cls, *args, **kwargs):
|
||||
'''
|
||||
Need to reset this special method or else
|
||||
dom_tag will think it's being used as a dectorator.
|
||||
|
||||
This means lazy() can't be used as a dectorator, but
|
||||
thinking about when you might want that just confuses me.
|
||||
'''
|
||||
return object.__new__(_cls)
|
||||
|
||||
def __init__(self, func, *args, **kwargs):
|
||||
super(lazy, self).__init__()
|
||||
self.func = func
|
||||
self.args = args
|
||||
self.kwargs = kwargs
|
||||
|
||||
|
||||
def _render(self, sb, *a, **kw):
|
||||
r = self.func(*self.args, **self.kwargs)
|
||||
sb.append(str(r))
|
||||
|
||||
|
||||
class text(dom_tag):
|
||||
'''
|
||||
Just a string. Useful for inside context managers
|
||||
'''
|
||||
is_pretty = False
|
||||
is_inline = True
|
||||
|
||||
def __init__(self, _text, escape=True):
|
||||
super(text, self).__init__()
|
||||
self.escape = escape
|
||||
if escape:
|
||||
self.text = str_escape(_text)
|
||||
else:
|
||||
self.text = _text
|
||||
|
||||
def _render(self, sb, *a, **kw):
|
||||
sb.append(self.text)
|
||||
return sb
|
||||
|
||||
|
||||
def raw(s):
|
||||
'''
|
||||
Inserts a raw string into the DOM. Unsafe. Alias for text(x, escape=False)
|
||||
'''
|
||||
return text(s, escape=False)
|
Reference in New Issue
Block a user