Best Python code snippet using fMBT_python
program.py
Source:program.py
1import re2try:3 import ast4except ImportError:5 from chameleon import ast25 as ast6try:7 str = unicode8except NameError:9 long = int10from functools import partial11from copy import copy12from ..program import ElementProgram13from ..namespaces import XML_NS14from ..namespaces import XMLNS_NS15from ..namespaces import I18N_NS as I18N16from ..namespaces import TAL_NS as TAL17from ..namespaces import METAL_NS as METAL18from ..namespaces import META_NS as META19from ..astutil import Static20from ..astutil import parse21from ..astutil import marker22from .. import tal23from .. import metal24from .. import i18n25from .. import nodes26from ..exc import LanguageError27from ..exc import ParseError28from ..exc import CompilationError29from ..utils import decode_htmlentities30try:31 str = unicode32except NameError:33 long = int34missing = object()35re_trim = re.compile(r'($\s+|\s+^)', re.MULTILINE)36EMPTY_DICT = Static(ast.Dict(keys=[], values=[]))37def skip(node):38 return node39def wrap(node, *wrappers):40 for wrapper in reversed(wrappers):41 node = wrapper(node)42 return node43def validate_attributes(attributes, namespace, whitelist):44 for ns, name in attributes:45 if ns == namespace and name not in whitelist:46 raise CompilationError(47 "Bad attribute for namespace '%s'" % ns, name48 )49class MacroProgram(ElementProgram):50 """Visitor class that generates a program for the ZPT language."""51 DEFAULT_NAMESPACES = {52 'xmlns': XMLNS_NS,53 'xml': XML_NS,54 'tal': TAL,55 'metal': METAL,56 'i18n': I18N,57 'meta': META,58 }59 DROP_NS = TAL, METAL, I18N, META60 VARIABLE_BLACKLIST = "default", "repeat", "nothing", \61 "convert", "decode", "translate"62 _interpolation_enabled = True63 _whitespace = "\n"64 _last = ""65 # Macro name (always trivial for a macro program)66 name = None67 # This default marker value has the semantics that if an68 # expression evaluates to that value, the expression default value69 # is returned. For an attribute, if there is no default, this70 # means that the attribute is dropped.71 default_marker = None72 # Escape mode (true value means XML-escape)73 escape = True74 # Attributes which should have boolean behavior (on true, the75 # value takes the attribute name, on false, the attribute is76 # dropped)77 boolean_attributes = set()78 # If provided, this should be a set of attributes for implicit79 # translation. Any attribute whose name is included in the set80 # will be translated even without explicit markup. Note that all81 # values should be lowercase strings.82 implicit_i18n_attributes = set()83 # If set, text will be translated even without explicit markup.84 implicit_i18n_translate = False85 # If set, additional attribute whitespace will be stripped.86 trim_attribute_space = False87 def __init__(self, *args, **kwargs):88 # Internal array for switch statements89 self._switches = []90 # Internal array for current use macro level91 self._use_macro = []92 # Internal array for current interpolation status93 self._interpolation = [True]94 # Internal dictionary of macro definitions95 self._macros = {}96 # Apply default values from **kwargs to self97 self._pop_defaults(98 kwargs,99 'boolean_attributes',100 'default_marker',101 'escape',102 'implicit_i18n_translate',103 'implicit_i18n_attributes',104 'trim_attribute_space',105 )106 super(MacroProgram, self).__init__(*args, **kwargs)107 @property108 def macros(self):109 macros = list(self._macros.items())110 macros.append((None, nodes.Sequence(self.body)))111 return tuple(112 nodes.Macro(name, [nodes.Context(node)])113 for name, node in macros114 )115 def visit_default(self, node):116 return nodes.Text(node)117 def visit_element(self, start, end, children):118 ns = start['ns_attrs']119 for (prefix, attr), encoded in tuple(ns.items()):120 if prefix == TAL:121 ns[prefix, attr] = decode_htmlentities(encoded)122 # Validate namespace attributes123 validate_attributes(ns, TAL, tal.WHITELIST)124 validate_attributes(ns, METAL, metal.WHITELIST)125 validate_attributes(ns, I18N, i18n.WHITELIST)126 # Check attributes for language errors127 self._check_attributes(start['namespace'], ns)128 # Remember whitespace for item repetition129 if self._last is not None:130 self._whitespace = "\n" + " " * len(self._last.rsplit('\n', 1)[-1])131 # Set element-local whitespace132 whitespace = self._whitespace133 # Set up switch134 try:135 clause = ns[TAL, 'switch']136 except KeyError:137 switch = None138 else:139 value = nodes.Value(clause)140 switch = value, nodes.Copy(value)141 self._switches.append(switch)142 body = []143 # Include macro144 use_macro = ns.get((METAL, 'use-macro'))145 extend_macro = ns.get((METAL, 'extend-macro'))146 if use_macro or extend_macro:147 omit = True148 slots = []149 self._use_macro.append(slots)150 if use_macro:151 inner = nodes.UseExternalMacro(152 nodes.Value(use_macro), slots, False153 )154 else:155 inner = nodes.UseExternalMacro(156 nodes.Value(extend_macro), slots, True157 )158 # -or- include tag159 else:160 content = nodes.Sequence(body)161 # tal:content162 try:163 clause = ns[TAL, 'content']164 except KeyError:165 pass166 else:167 key, value = tal.parse_substitution(clause)168 xlate = True if ns.get((I18N, 'translate')) == '' else False169 content = self._make_content_node(value, content, key, xlate)170 if end is None:171 # Make sure start-tag has opening suffix.172 start['suffix'] = ">"173 # Explicitly set end-tag.174 end = {175 'prefix': '</',176 'name': start['name'],177 'space': '',178 'suffix': '>'179 }180 # i18n:translate181 try:182 clause = ns[I18N, 'translate']183 except KeyError:184 pass185 else:186 dynamic = ns.get((TAL, 'content')) or ns.get((TAL, 'replace'))187 if not dynamic:188 content = nodes.Translate(clause, content)189 # tal:attributes190 try:191 clause = ns[TAL, 'attributes']192 except KeyError:193 TAL_ATTRIBUTES = []194 else:195 TAL_ATTRIBUTES = tal.parse_attributes(clause)196 # i18n:attributes197 try:198 clause = ns[I18N, 'attributes']199 except KeyError:200 I18N_ATTRIBUTES = {}201 else:202 I18N_ATTRIBUTES = i18n.parse_attributes(clause)203 # Prepare attributes from TAL language204 prepared = tal.prepare_attributes(205 start['attrs'], TAL_ATTRIBUTES,206 I18N_ATTRIBUTES, ns, self.DROP_NS207 )208 # Create attribute nodes209 STATIC_ATTRIBUTES = self._create_static_attributes(prepared)210 ATTRIBUTES = self._create_attributes_nodes(211 prepared, I18N_ATTRIBUTES, STATIC_ATTRIBUTES212 )213 # Start- and end nodes214 start_tag = nodes.Start(215 start['name'],216 self._maybe_trim(start['prefix']),217 self._maybe_trim(start['suffix']),218 ATTRIBUTES219 )220 end_tag = nodes.End(221 end['name'],222 end['space'],223 self._maybe_trim(end['prefix']),224 self._maybe_trim(end['suffix']),225 ) if end is not None else None226 # tal:omit-tag227 try:228 clause = ns[TAL, 'omit-tag']229 except KeyError:230 omit = False231 else:232 clause = clause.strip()233 if clause == "":234 omit = True235 else:236 expression = nodes.Negate(nodes.Value(clause))237 omit = expression238 # Wrap start- and end-tags in condition239 start_tag = nodes.Condition(expression, start_tag)240 if end_tag is not None:241 end_tag = nodes.Condition(expression, end_tag)242 if omit is True or start['namespace'] in self.DROP_NS:243 inner = content244 else:245 inner = nodes.Element(246 start_tag,247 end_tag,248 content,249 )250 # Assign static attributes dictionary to "attrs" value251 inner = nodes.Define(252 [nodes.Alias(["attrs"], STATIC_ATTRIBUTES or EMPTY_DICT)],253 inner,254 )255 if omit is not False:256 inner = nodes.Cache([omit], inner)257 # tal:replace258 try:259 clause = ns[TAL, 'replace']260 except KeyError:261 pass262 else:263 key, value = tal.parse_substitution(clause)264 xlate = True if ns.get((I18N, 'translate')) == '' else False265 inner = self._make_content_node(value, inner, key, xlate)266 # metal:define-slot267 try:268 clause = ns[METAL, 'define-slot']269 except KeyError:270 DEFINE_SLOT = skip271 else:272 DEFINE_SLOT = partial(nodes.DefineSlot, clause)273 # tal:define274 try:275 clause = ns[TAL, 'define']276 except KeyError:277 DEFINE = skip278 else:279 defines = tal.parse_defines(clause)280 if defines is None:281 raise ParseError("Invalid define syntax.", clause)282 DEFINE = partial(283 nodes.Define,284 [nodes.Assignment(285 names, nodes.Value(expr), context == "local")286 for (context, names, expr) in defines],287 )288 # tal:case289 try:290 clause = ns[TAL, 'case']291 except KeyError:292 CASE = skip293 else:294 value = nodes.Value(clause)295 for switch in reversed(self._switches):296 if switch is not None:297 break298 else:299 raise LanguageError(300 "Must define switch on a parent element.", clause301 )302 CASE = lambda node: nodes.Define(303 [nodes.Alias(["default"], switch[1], False)],304 nodes.Condition(305 nodes.Equality(switch[0], value),306 nodes.Cancel([switch[0]], node),307 ))308 # tal:repeat309 try:310 clause = ns[TAL, 'repeat']311 except KeyError:312 REPEAT = skip313 else:314 defines = tal.parse_defines(clause)315 assert len(defines) == 1316 context, names, expr = defines[0]317 expression = nodes.Value(expr)318 if start['namespace'] == TAL:319 self._last = None320 self._whitespace = whitespace.lstrip('\n')321 whitespace = ""322 REPEAT = partial(323 nodes.Repeat,324 names,325 expression,326 context == "local",327 whitespace328 )329 # tal:condition330 try:331 clause = ns[TAL, 'condition']332 except KeyError:333 CONDITION = skip334 else:335 expression = nodes.Value(clause)336 CONDITION = partial(nodes.Condition, expression)337 # tal:switch338 if switch is None:339 SWITCH = skip340 else:341 SWITCH = partial(nodes.Cache, list(switch))342 # i18n:domain343 try:344 clause = ns[I18N, 'domain']345 except KeyError:346 DOMAIN = skip347 else:348 DOMAIN = partial(nodes.Domain, clause)349 # i18n:name350 try:351 clause = ns[I18N, 'name']352 except KeyError:353 NAME = skip354 else:355 if not clause.strip():356 NAME = skip357 else:358 NAME = partial(nodes.Name, clause)359 # The "slot" node next is the first node level that can serve360 # as a macro slot361 slot = wrap(362 inner,363 DEFINE_SLOT,364 DEFINE,365 CASE,366 CONDITION,367 REPEAT,368 SWITCH,369 DOMAIN,370 )371 # metal:fill-slot372 try:373 clause = ns[METAL, 'fill-slot']374 except KeyError:375 pass376 else:377 if not clause.strip():378 raise LanguageError(379 "Must provide a non-trivial string for metal:fill-slot.",380 clause381 )382 index = -(1 + int(bool(use_macro or extend_macro)))383 try:384 slots = self._use_macro[index]385 except IndexError:386 raise LanguageError(387 "Cannot use metal:fill-slot without metal:use-macro.",388 clause389 )390 slots = self._use_macro[index]391 slots.append(nodes.FillSlot(clause, slot))392 # metal:define-macro393 try:394 clause = ns[METAL, 'define-macro']395 except KeyError:396 pass397 else:398 self._macros[clause] = slot399 slot = nodes.UseInternalMacro(clause)400 slot = wrap(401 slot,402 NAME403 )404 # tal:on-error405 try:406 clause = ns[TAL, 'on-error']407 except KeyError:408 ON_ERROR = skip409 else:410 key, value = tal.parse_substitution(clause)411 translate = True if ns.get((I18N, 'translate')) == '' else False412 fallback = self._make_content_node(value, None, key, translate)413 if omit is False and start['namespace'] not in self.DROP_NS:414 start_tag = copy(start_tag)415 start_tag.attributes = nodes.Sequence(416 start_tag.attributes.extract(417 lambda attribute:418 isinstance(attribute, nodes.Attribute) and419 isinstance(attribute.expression, ast.Str)420 )421 )422 if end_tag is None:423 # Make sure start-tag has opening suffix. We don't424 # allow self-closing element here.425 start_tag.suffix = ">"426 # Explicitly set end-tag.427 end_tag = nodes.End(start_tag.name, '', '</', '>',)428 fallback = nodes.Element(429 start_tag,430 end_tag,431 fallback,432 )433 ON_ERROR = partial(nodes.OnError, fallback, 'error')434 clause = ns.get((META, 'interpolation'))435 if clause in ('false', 'off'):436 INTERPOLATION = False437 elif clause in ('true', 'on'):438 INTERPOLATION = True439 elif clause is None:440 INTERPOLATION = self._interpolation[-1]441 else:442 raise LanguageError("Bad interpolation setting.", clause)443 self._interpolation.append(INTERPOLATION)444 # Visit content body445 for child in children:446 body.append(self.visit(*child))447 self._switches.pop()448 self._interpolation.pop()449 if use_macro:450 self._use_macro.pop()451 return wrap(452 slot,453 ON_ERROR454 )455 def visit_start_tag(self, start):456 return self.visit_element(start, None, [])457 def visit_cdata(self, node):458 if not self._interpolation[-1] or not '${' in node:459 return nodes.Text(node)460 expr = nodes.Substitution(node, ())461 return nodes.Interpolation(expr, True, False)462 def visit_comment(self, node):463 if node.startswith('<!--!'):464 return465 if node.startswith('<!--?'):466 return nodes.Text('<!--' + node.lstrip('<!-?'))467 if not self._interpolation[-1] or not '${' in node:468 return nodes.Text(node)469 char_escape = ('&', '<', '>') if self.escape else ()470 expression = nodes.Substitution(node[4:-3], char_escape)471 return nodes.Sequence(472 [nodes.Text(node[:4]),473 nodes.Interpolation(expression, True, False),474 nodes.Text(node[-3:])475 ])476 def visit_processing_instruction(self, node):477 if node['name'] != 'python':478 text = '<?' + node['name'] + node['text'] + '?>'479 return self.visit_text(text)480 return nodes.CodeBlock(node['text'])481 def visit_text(self, node):482 self._last = node483 translation = self.implicit_i18n_translate484 if self._interpolation[-1] and '${' in node:485 char_escape = ('&', '<', '>') if self.escape else ()486 expression = nodes.Substitution(node, char_escape)487 return nodes.Interpolation(expression, True, translation)488 if not translation:489 return nodes.Text(node)490 match = re.search(r'(\s*)(.*\S)(\s*)', node, flags=re.DOTALL)491 if match is not None:492 prefix, text, suffix = match.groups()493 normalized = re.sub('\s+', ' ', text)494 return nodes.Sequence([495 nodes.Text(prefix),496 nodes.Translate(normalized, nodes.Text(normalized)),497 nodes.Text(suffix),498 ])499 else:500 return nodes.Text(node)501 def _pop_defaults(self, kwargs, *attributes):502 for attribute in attributes:503 default = getattr(self, attribute)504 value = kwargs.pop(attribute, default)505 setattr(self, attribute, value)506 def _check_attributes(self, namespace, ns):507 if namespace in self.DROP_NS and ns.get((TAL, 'attributes')):508 raise LanguageError(509 "Dynamic attributes not allowed on elements of "510 "the namespace: %s." % namespace,511 ns[TAL, 'attributes'],512 )513 script = ns.get((TAL, 'script'))514 if script is not None:515 raise LanguageError(516 "The script attribute is unsupported.", script)517 tal_content = ns.get((TAL, 'content'))518 if tal_content and ns.get((TAL, 'replace')):519 raise LanguageError(520 "You cannot use tal:content and tal:replace at the same time.",521 tal_content522 )523 if tal_content and ns.get((I18N, 'translate')):524 raise LanguageError(525 "You cannot use tal:content with non-trivial i18n:translate.",526 tal_content527 )528 def _make_content_node(self, expression, default, key, translate):529 value = nodes.Value(expression)530 char_escape = ('&', '<', '>') if key == 'text' else ()531 content = nodes.Content(value, char_escape, translate)532 if default is not None:533 content = nodes.Condition(534 nodes.Identity(value, marker("default")),535 default,536 content,537 )538 # Cache expression to avoid duplicate evaluation539 content = nodes.Cache([value], content)540 # Define local marker "default"541 content = nodes.Define(542 [nodes.Alias(["default"], marker("default"))],543 content544 )545 return content546 def _create_attributes_nodes(self, prepared, I18N_ATTRIBUTES, STATIC):547 attributes = []548 names = [attr[0] for attr in prepared]549 filtering = [[]]550 for i, (name, text, quote, space, eq, expr) in enumerate(prepared):551 implicit_i18n = (552 name is not None and553 name.lower() in self.implicit_i18n_attributes554 )555 char_escape = ('&', '<', '>', quote)556 # Use a provided default text as the default marker557 # (aliased to the name ``default``), otherwise use the558 # program's default marker value.559 if text is not None:560 default_marker = ast.Str(s=text)561 else:562 default_marker = self.default_marker563 msgid = I18N_ATTRIBUTES.get(name, missing)564 # If (by heuristic) ``text`` contains one or more565 # interpolation expressions, apply interpolation566 # substitution to the text567 if expr is None and text is not None and '${' in text:568 expr = nodes.Substitution(text, char_escape, None)569 translation = implicit_i18n and msgid is missing570 value = nodes.Interpolation(expr, True, translation)571 default_marker = self.default_marker572 # If the expression is non-trivial, the attribute is573 # dynamic (computed).574 elif expr is not None:575 if name is None:576 expression = nodes.Value(expr)577 value = nodes.DictAttributes(578 expression, ('&', '<', '>', '"'), '"',579 set(filter(None, names[i:]))580 )581 for fs in filtering:582 fs.append(expression)583 filtering.append([])584 elif name in self.boolean_attributes:585 value = nodes.Boolean(expr, name)586 else:587 if text is not None:588 default = default_marker589 else:590 default = None591 value = nodes.Substitution(expr, char_escape, default)592 # Otherwise, it's a static attribute. We don't include it593 # here if there's one or more "computed" attributes594 # (dynamic, from one or more dict values).595 else:596 value = ast.Str(s=text)597 if msgid is missing and implicit_i18n:598 msgid = text599 if name is not None:600 # If translation is required, wrap in a translation601 # clause602 if msgid is not missing:603 value = nodes.Translate(msgid, value)604 space = self._maybe_trim(space)605 fs = filtering[-1]606 attribute = nodes.Attribute(name, value, quote, eq, space, fs)607 if not isinstance(value, ast.Str):608 # Always define a ``default`` alias for non-static609 # expressions.610 attribute = nodes.Define(611 [nodes.Alias(["default"], default_marker)],612 attribute,613 )614 value = attribute615 attributes.append(value)616 result = nodes.Sequence(attributes)617 fs = filtering[0]618 if fs:619 return nodes.Cache(fs, result)620 return result621 def _create_static_attributes(self, prepared):622 static_attrs = {}623 for name, text, quote, space, eq, expr in prepared:624 if name is None:625 continue626 static_attrs[name] = text if text is not None else expr627 if not static_attrs:628 return629 return Static(parse(repr(static_attrs)).body)630 def _maybe_trim(self, string):631 if self.trim_attribute_space:632 return re_trim.sub(" ", string)...
tal.py
Source:tal.py
1##############################################################################2#3# Copyright (c) 2001, 2002 Zope Foundation and Contributors.4# All Rights Reserved.5#6# This software is subject to the provisions of the Zope Public License,7# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.8# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED9# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED10# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS11# FOR A PARTICULAR PURPOSE.12#13##############################################################################14import re15import copy16from .exc import LanguageError17from .utils import descriptorint18from .utils import descriptorstr19from .namespaces import XMLNS_NS20from .parser import groups21try:22 next23except NameError:24 from chameleon.py25 import next25try:26 # optional library: `zope.interface`27 from chameleon import interfaces28 import zope.interface29except ImportError:30 interfaces = None31NAME = r"[a-zA-Z_][-a-zA-Z0-9_]*"32DEFINE_RE = re.compile(r"(?s)\s*(?:(global|local)\s+)?" +33 r"(%s|\(%s(?:,\s*%s)*\))\s+(.*)\Z" % (NAME, NAME, NAME),34 re.UNICODE)35SUBST_RE = re.compile(r"\s*(?:(text|structure)\s+)?(.*)\Z", re.S | re.UNICODE)36ATTR_RE = re.compile(r"\s*([^\s{}'\"]+)\s+([^\s].*)\Z", re.S | re.UNICODE)37ENTITY_RE = re.compile(r'(&(#?)(x?)(\d{1,5}|\w{1,8});)')38WHITELIST = frozenset([39 "define",40 "comment",41 "condition",42 "content",43 "replace",44 "repeat",45 "attributes",46 "on-error",47 "omit-tag",48 "script",49 "switch",50 "case",51 "xmlns",52 "xml"53 ])54def split_parts(arg):55 # Break in pieces at undoubled semicolons and56 # change double semicolons to singles:57 i = 058 while i < len(arg):59 m = ENTITY_RE.search(arg[i:])60 if m is None:61 break62 arg = arg[:i + m.end()] + ';' + arg[i + m.end():]63 i += m.end()64 arg = arg.replace(";;", "\0")65 parts = arg.split(';')66 parts = [p.replace("\0", ";") for p in parts]67 if len(parts) > 1 and not parts[-1].strip():68 del parts[-1] # It ended in a semicolon69 return parts70def parse_attributes(clause):71 attrs = []72 seen = set()73 for part in split_parts(clause):74 m = ATTR_RE.match(part)75 if not m:76 name, expr = None, part.strip()77 else:78 name, expr = groups(m, part)79 if name in seen:80 raise LanguageError(81 "Duplicate attribute name in attributes.", part)82 seen.add(name)83 attrs.append((name, expr))84 return attrs85def parse_substitution(clause):86 m = SUBST_RE.match(clause)87 if m is None:88 raise LanguageError(89 "Invalid content substitution syntax.", clause)90 key, expression = groups(m, clause)91 if not key:92 key = "text"93 return key, expression94def parse_defines(clause):95 """96 Parses a tal:define value.97 # Basic syntax, implicit local98 >>> parse_defines('hello lovely')99 [('local', ('hello',), 'lovely')]100 # Explicit local101 >>> parse_defines('local hello lovely')102 [('local', ('hello',), 'lovely')]103 # With global104 >>> parse_defines('global hello lovely')105 [('global', ('hello',), 'lovely')]106 # Multiple expressions107 >>> parse_defines('hello lovely; tea time')108 [('local', ('hello',), 'lovely'), ('local', ('tea',), 'time')]109 # With multiple names110 >>> parse_defines('(hello, howdy) lovely')111 [('local', ['hello', 'howdy'], 'lovely')]112 # With unicode whitespace113 >>> try:114 ... s = '\xc2\xa0hello lovely'.decode('utf-8')115 ... except AttributeError:116 ... s = '\xa0hello lovely'117 >>> from chameleon.utils import unicode_string118 >>> parse_defines(s) == [119 ... ('local', ('hello',), 'lovely')120 ... ]121 True122 """123 defines = []124 for part in split_parts(clause):125 m = DEFINE_RE.match(part)126 if m is None:127 raise LanguageError("Invalid define syntax", part)128 context, name, expr = groups(m, part)129 context = context or "local"130 if name.startswith('('):131 names = [n.strip() for n in name.strip('()').split(',')]132 else:133 names = (name,)134 defines.append((context, names, expr))135 return defines136def prepare_attributes(attrs, dyn_attributes, i18n_attributes,137 ns_attributes, drop_ns):138 drop = set([attribute['name'] for attribute, (ns, value)139 in zip(attrs, ns_attributes)140 if ns in drop_ns or (141 ns == XMLNS_NS and142 attribute['value'] in drop_ns143 )144 ])145 attributes = []146 normalized = {}147 computed = []148 for attribute in attrs:149 name = attribute['name']150 if name in drop:151 continue152 attributes.append((153 name,154 attribute['value'],155 attribute['quote'],156 attribute['space'],157 attribute['eq'],158 None,159 ))160 normalized[name.lower()] = len(attributes) - 1161 for name, expr in dyn_attributes:162 index = normalized.get(name.lower()) if name else None163 if index is not None:164 _, text, quote, space, eq, _ = attributes[index]165 add = attributes.__setitem__166 else:167 text = None168 quote = '"'169 space = " "170 eq = "="171 index = len(attributes)172 add = attributes.insert173 if name is not None:174 normalized[name.lower()] = len(attributes) - 1175 attribute = name, text, quote, space, eq, expr176 add(index, attribute)177 for name in i18n_attributes:178 attr = name.lower()179 if attr not in normalized:180 attributes.append((name, name, '"', " ", "=", None))181 normalized[attr] = len(attributes) - 1182 return attributes183class RepeatItem(object):184 __slots__ = "length", "_iterator"185 __allow_access_to_unprotected_subobjects__ = True186 def __init__(self, iterator, length):187 self.length = length188 self._iterator = iterator189 def __iter__(self):190 return self._iterator191 try:192 iter(()).__len__193 except AttributeError:194 @descriptorint195 def index(self):196 try:197 remaining = self._iterator.__length_hint__()198 except AttributeError:199 remaining = len(tuple(copy.copy(self._iterator)))200 return self.length - remaining - 1201 else:202 @descriptorint203 def index(self):204 remaining = self._iterator.__len__()205 return self.length - remaining - 1206 @descriptorint207 def start(self):208 return self.index == 0209 @descriptorint210 def end(self):211 return self.index == self.length - 1212 @descriptorint213 def number(self):214 return self.index + 1215 @descriptorstr216 def odd(self):217 """Returns a true value if the item index is odd.218 >>> it = RepeatItem(iter(("apple", "pear")), 2)219 >>> next(it._iterator)220 'apple'221 >>> it.odd()222 ''223 >>> next(it._iterator)224 'pear'225 >>> it.odd()226 'odd'227 """228 return self.index % 2 == 1 and 'odd' or ''229 @descriptorstr230 def even(self):231 """Returns a true value if the item index is even.232 >>> it = RepeatItem(iter(("apple", "pear")), 2)233 >>> next(it._iterator)234 'apple'235 >>> it.even()236 'even'237 >>> next(it._iterator)238 'pear'239 >>> it.even()240 ''241 """242 return self.index % 2 == 0 and 'even' or ''243 def next(self):244 raise NotImplementedError(245 "Method not implemented (can't update local variable).")246 def _letter(self, base=ord('a'), radix=26):247 """Get the iterator position as a lower-case letter248 >>> it = RepeatItem(iter(("apple", "pear", "orange")), 3)249 >>> next(it._iterator)250 'apple'251 >>> it.letter()252 'a'253 >>> next(it._iterator)254 'pear'255 >>> it.letter()256 'b'257 >>> next(it._iterator)258 'orange'259 >>> it.letter()260 'c'261 """262 index = self.index263 if index < 0:264 raise TypeError("No iteration position")265 s = ""266 while 1:267 index, off = divmod(index, radix)268 s = chr(base + off) + s269 if not index:270 return s271 letter = descriptorstr(_letter)272 @descriptorstr273 def Letter(self):274 """Get the iterator position as an upper-case letter275 >>> it = RepeatItem(iter(("apple", "pear", "orange")), 3)276 >>> next(it._iterator)277 'apple'278 >>> it.Letter()279 'A'280 >>> next(it._iterator)281 'pear'282 >>> it.Letter()283 'B'284 >>> next(it._iterator)285 'orange'286 >>> it.Letter()287 'C'288 """289 return self._letter(base=ord('A'))290 @descriptorstr291 def Roman(self, rnvalues=(292 (1000, 'M'), (900, 'CM'), (500, 'D'), (400, 'CD'),293 (100, 'C'), (90, 'XC'), (50, 'L'), (40, 'XL'),294 (10, 'X'), (9, 'IX'), (5, 'V'), (4, 'IV'), (1, 'I'))):295 """Get the iterator position as an upper-case roman numeral296 >>> it = RepeatItem(iter(("apple", "pear", "orange")), 3)297 >>> next(it._iterator)298 'apple'299 >>> it.Roman()300 'I'301 >>> next(it._iterator)302 'pear'303 >>> it.Roman()304 'II'305 >>> next(it._iterator)306 'orange'307 >>> it.Roman()308 'III'309 """310 n = self.index + 1311 s = ""312 for v, r in rnvalues:313 rct, n = divmod(n, v)314 s = s + r * rct315 return s316 @descriptorstr317 def roman(self):318 """Get the iterator position as a lower-case roman numeral319 >>> it = RepeatItem(iter(("apple", "pear", "orange")), 3)320 >>> next(it._iterator)321 'apple'322 >>> it.roman()323 'i'324 >>> next(it._iterator)325 'pear'326 >>> it.roman()327 'ii'328 >>> next(it._iterator)329 'orange'330 >>> it.roman()331 'iii'332 """333 return self.Roman().lower()334if interfaces is not None:335 zope.interface.classImplements(RepeatItem, interfaces.ITALESIterator)336class RepeatDict(dict):337 """Repeat dictionary implementation.338 >>> repeat = RepeatDict({})339 >>> iterator, length = repeat('numbers', range(5))340 >>> length341 5342 >>> repeat['numbers']343 <chameleon.tal.RepeatItem object at ...>344 >>> repeat.numbers345 <chameleon.tal.RepeatItem object at ...>346 >>> getattr(repeat, 'missing_key', None) is None347 True348 >>> try:349 ... from chameleon import interfaces350 ... interfaces.ITALESIterator(repeat,None) is None351 ... except ImportError:352 ... True353 ...354 True355 """356 __slots__ = "__setitem__", "__getitem__"357 def __init__(self, d):358 self.__setitem__ = d.__setitem__359 self.__getitem__ = d.__getitem__360 def __getattr__(self,key):361 try:362 return self[key]363 except KeyError:364 raise AttributeError(key)365 def __call__(self, key, iterable):366 """We coerce the iterable to a tuple and return an iterator367 after registering it in the repeat dictionary."""368 iterable = tuple(iterable)369 length = len(iterable)370 iterator = iter(iterable)371 # Insert as repeat item372 self[key] = RepeatItem(iterator, length)373 return iterator, length374class ErrorInfo(object):375 """Information about an exception passed to an on-error handler."""376 def __init__(self, err, position=(None, None)):377 if isinstance(err, Exception):378 self.type = err.__class__379 self.value = err380 else:381 self.type = err382 self.value = None383 self.lineno = position[0]384 self.offset = position[1]385if interfaces is not None:...
internals.py
Source:internals.py
1import logging2logger = logging.getLogger('anabot.preprocessor')3import re4from . import EASY_NS_URIS5from .decorators import _REPLACES6from .functions import tag_elements7DROP_NS_RE = re.compile(r'/[^:/ ]+:')8DROP_NS = lambda x: DROP_NS_RE.sub('/', x)9DROP_NUM_RE = re.compile(r'\[[0-9]+\]')10DROP_NUM = lambda x: DROP_NUM_RE.sub('', x)11def do_replace(element):12 node_path = DROP_NS(DROP_NUM(element.nodePath()))13 _REPLACES.get(node_path, _REPLACES[None])(element)14 element.setNs(None)15def remove_easy_namespace(document):16 for element in document.xpathEval('//*'):17 for EASY_NS_URI in EASY_NS_URIS:...
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!