Best Python code snippet using autotest_python
jsontemplate.py
Source:jsontemplate.py  
...100    if formatter:101      return formatter102    else:103      raise BadFormatter('%r is not a valid formatter' % format_str)104  def AppendSubstitution(self, name, formatters):105    formatters = [self._GetFormatter(f) for f in formatters]106    self.current_block.Append((_DoSubstitute, (name, formatters)))107  def NewSection(self, repeated, section_name):108    """For sections or repeated sections."""109    new_block = _Section(section_name)110    if repeated:111      func = _DoRepeatedSection112    else:113      func = _DoSection114    self.current_block.Append((func, new_block))115    self.stack.append(new_block)116    self.current_block = new_block117  def NewClause(self, name):118    # TODO: Raise errors if the clause isn't appropriate for the current block119    # isn't a 'repeated section' (e.g. alternates with in a non-repeated120    # section)121    self.current_block.NewClause(name)122  def EndSection(self):123    self.stack.pop()124    self.current_block = self.stack[-1]125  def Root(self):126    # It's assumed that we call this at the end of the program127    return self.current_block128class _Section(object):129  """Represents a (repeated) section."""130  def __init__(self, section_name=None):131    """132    Args:133      section_name: name given as an argument to the section134    """135    self.section_name = section_name136    # Pairs of func, args, or a literal string137    self.current_clause = []138    self.statements = {'default': self.current_clause}139  def __repr__(self):140    return '<Block %s>' % self.section_name141  def Statements(self, clause='default'):142    return self.statements.get(clause, [])143  def NewClause(self, clause_name):144    new_clause = []145    self.statements[clause_name] = new_clause146    self.current_clause = new_clause147  def Append(self, statement):148    """Append a statement to this block."""149    self.current_clause.append(statement)150class _ScopedContext(object):151  """Allows scoped lookup of variables.152  If the variable isn't in the current context, then we search up the stack.153  """154  def __init__(self, context):155    self.stack = [context]156  def PushSection(self, name):157    new_context = self.stack[-1].get(name)158    self.stack.append(new_context)159    return new_context160  def Pop(self):161    self.stack.pop()162  def CursorValue(self):163    return self.stack[-1]164  def __iter__(self):165    """Assumes that the top of the stack is a list."""166    # The top of the stack is always the current context.167    self.stack.append(None)168    for item in self.stack[-2]:169      self.stack[-1] = item170      yield item171    self.stack.pop()172  def Lookup(self, name):173    """174    Get the value associated with a name in the current context.  The current175    context could be an dictionary in a list, or a dictionary outside a list.176    """177    i = len(self.stack) - 1178    while 1:179      context = self.stack[i]180      if not isinstance(context, dict):  # Can't look up names in a list or atom181        i -= 1182      else:183        value = context.get(name)184        if value is None:  # A key of None or a missing key are treated the same185          i -= 1186        else:187          return value188      if i <= -1:  # Couldn't find it anywhere189        raise UndefinedVariable('%r is not defined' % name)190def _ToString(x):191  if type(x) in (str, unicode):192    return x193  else:194    return pprint.pformat(x)195def _HtmlAttrValue(x):196  return cgi.escape(x, quote=True)197# See http://google-ctemplate.googlecode.com/svn/trunk/doc/howto.html for more198# escape types.199#200# Also, we might want to take a look at Django filters.201#202# This is a *public* constant, so that callers can use it construct their own203# formatter lookup dictionaries, and pass them in to Template.204_DEFAULT_FORMATTERS = {205    'html': cgi.escape,206    # The 'htmltag' name is deprecated.  The html-attr-value name is preferred207    # because it can be read with "as":208    #   {url|html-attr-value} means:209    #   "substitute 'url' as an HTML attribute value"210    'html-attr-value': _HtmlAttrValue,211    'htmltag': _HtmlAttrValue,212    'raw': lambda x: x,213    # Used for the length of a list.  Can be used for the size of a dictionary214    # too, though I haven't run into that use case.215    'size': lambda value: str(len(value)),216    # The argument is a dictionary, and we get a a=1&b=2 string back.217    'url-params': urllib.urlencode,  218    # The argument is an atom, and it takes 'Search query?' -> 'Search+query%3F'219    'url-param-value': urllib.quote_plus,  # param is an atom220    # The default formatter, when no other default is specifier.  For debugging,221    # this could be lambda x: json.dumps(x, indent=2), but here we want to be222    # compatible to Python 2.4.223    'str': _ToString,224    # Just show a plain URL on an HTML page (without anchor text).225    'plain-url': lambda x: '<a href="%s">%s</a>' % (226        cgi.escape(x, quote=True), cgi.escape(x)),227    # Placeholders for "standard names".  We're not including them by default228    # since they require additional dependencies.  We can provide a part of the229    # "lookup chain" in formatters.py for people people want the dependency.230    231    # 'json' formats arbitrary data dictionary nodes as JSON strings.  'json'232    # and 'js-string' are identical (since a JavaScript string *is* JSON).  The233    # latter is meant to be serve as extra documentation when you want a string234    # argument only, which is a common case.  235    'json': None,236    'js-string': None,237    }238def SplitMeta(meta):239  """Split and validate metacharacters.240  Example: '{}' -> ('{', '}')241  This is public so the syntax highlighter and other tools can use it.242  """243  n = len(meta)244  if n % 2 == 1:245    raise ConfigurationError(246        '%r has an odd number of metacharacters' % meta)247  return meta[:n/2], meta[n/2:]248_token_re_cache = {}249def MakeTokenRegex(meta_left, meta_right):250  """Return a (compiled) regular expression for tokenization.251  Args:252    meta_left, meta_right: e.g. '{' and '}'253  - The regular expressions are memoized.254  - This function is public so the syntax highlighter can use it.255  """256  key = meta_left, meta_right257  if key not in _token_re_cache:258    # Need () for re.split259    _token_re_cache[key] = re.compile(260        r'(' +261        re.escape(meta_left) +262        # For simplicity, we allow all characters except newlines inside263        # metacharacters ({} / [])264        r'.+?' +265        re.escape(meta_right) +266        # Some declarations also include the newline at the end -- that is, we267        # don't expand the newline in that case268        r'\n?)')269  return _token_re_cache[key]270def CompileTemplate(271    template_str, builder=None, meta='{}', format_char='|',272    more_formatters=lambda x: None, default_formatter='str'):273  """Compile the template string, calling methods on the 'program builder'.274  Args:275    template_str: The template string.  It should not have any compilation276        options in the header -- those are parsed by FromString/FromFile277    builder: Something with the interface of _ProgramBuilder278    meta: The metacharacters to use279    more_formatters: A function which maps format strings to280        *other functions*.  The resulting functions should take a data281        dictionary value (a JSON atom, or a dictionary itself), and return a282        string to be shown on the page.  These are often used for HTML escaping,283        etc.  There is a default set of formatters available if more_formatters284        is not passed.285    default_formatter: The formatter to use for substitutions that are missing a286        formatter.  The 'str' formatter the "default default" -- it just tries287        to convert the context value to a string in some unspecified manner.288  Returns:289    The compiled program (obtained from the builder)290  Raises:291    The various subclasses of CompilationError.  For example, if292    default_formatter=None, and a variable is missing a formatter, then293    MissingFormatter is raised.294  This function is public so it can be used by other tools, e.g. a syntax295  checking tool run before submitting a template to source control.296  """297  builder = builder or _ProgramBuilder(more_formatters)298  meta_left, meta_right = SplitMeta(meta)299  # : is meant to look like Python 3000 formatting {foo:.3f}.  According to300  # PEP 3101, that's also what .NET uses.301  # | is more readable, but, more importantly, reminiscent of pipes, which is302  # useful for multiple formatters, e.g. {name|js-string|html}303  if format_char not in (':', '|'):304    raise ConfigurationError(305        'Only format characters : and | are accepted (got %r)' % format_char)306  # Need () for re.split307  token_re = MakeTokenRegex(meta_left, meta_right)308  tokens = token_re.split(template_str)309  # If we go to -1, then we got too many {end}.  If end at 1, then we're missing310  # an {end}.311  balance_counter = 0312  for i, token in enumerate(tokens):313    # By the definition of re.split, even tokens are literal strings, and odd314    # tokens are directives.315    if i % 2 == 0:316      # A literal string317      if token:318        builder.Append(token)319    else:320      had_newline = False321      if token.endswith('\n'):322        token = token[:-1]323        had_newline = True324      assert token.startswith(meta_left), token325      assert token.endswith(meta_right), token326      token = token[len(meta_left) : -len(meta_right)]327      # It's a comment328      if token.startswith('#'):329        continue330      # It's a "keyword" directive331      if token.startswith('.'):332        token = token[1:]333        literal = {334            'meta-left': meta_left,335            'meta-right': meta_right,336            'space': ' ',337            }.get(token)338        if literal is not None:339          builder.Append(literal)340          continue341        match = _SECTION_RE.match(token)342        if match:343          repeated, _, section_name = match.groups()344          builder.NewSection(repeated, section_name)345          balance_counter += 1346          continue347        if token in ('or', 'alternates with'):348          builder.NewClause(token)349          continue350        if token == 'end':351          balance_counter -= 1352          if balance_counter < 0:353            # TODO: Show some context for errors354            raise TemplateSyntaxError(355                'Got too many %send%s statements.  You may have mistyped an '356                "earlier 'section' or 'repeated section' directive."357                % (meta_left, meta_right))358          builder.EndSection()359          continue360      # Now we know the directive is a substitution.361      parts = token.split(format_char)362      if len(parts) == 1:363        if default_formatter is None:364          raise MissingFormatter('This template requires explicit formatters.')365        # If no formatter is specified, the default is the 'str' formatter,366        # which the user can define however they desire.367        name = token368        formatters = [default_formatter]369      else:370        name = parts[0]371        formatters = parts[1:]372      builder.AppendSubstitution(name, formatters)373      if had_newline:374        builder.Append('\n')375  if balance_counter != 0:376    raise TemplateSyntaxError('Got too few %send%s statements' %377        (meta_left, meta_right))378  return builder.Root()379_OPTION_RE = re.compile(r'^([a-zA-Z\-]+):\s*(.*)')380# TODO: whitespace mode, etc.381_OPTION_NAMES = ['meta', 'format-char', 'default-formatter']382def FromString(s, more_formatters=lambda x: None, _constructor=None):383  """Like FromFile, but takes a string."""384  f = cStringIO.StringIO(s)385  return FromFile(f, more_formatters=more_formatters, _constructor=_constructor)386def FromFile(f, more_formatters=lambda x: None, _constructor=None):...visitor.py
Source:visitor.py  
1import typing2import pathlib3import re4from bzd.parser.element import Element, Sequence5from bzd.parser.visitor import Visitor as VisitorBase6from bzd.parser.error import Error, ExceptionParser7# Needed by the include method8import bzd.template.template9from bzd.template.substitution import SubstitutionsAccessor, SubstitutionWrapper10ResultType = typing.List[str]11class Loop:12	def __init__(self, parent: typing.Optional["Loop"]) -> None:13		self.parent = parent14		self.index: int = 015	@property16	def first(self) -> bool:17		return self.index == 018	def _inc(self) -> None:19		self.index += 120class Visitor(VisitorBase[ResultType, ResultType]):21	nestedKind = None22	def __init__(self,23		substitutions: typing.Union[SubstitutionsAccessor, SubstitutionWrapper],24		includeDirs: typing.Sequence[pathlib.Path] = [pathlib.Path(__file__).parent.parent.parent.parent],25		indent: bool = False) -> None:26		# Re-use directly substitution wrapper if provided.27		# This is needed by the include control block, as we want macros (for example) to be executed28		# with the current substition object and not a copy at a given time.29		self.substitutions = substitutions if isinstance(substitutions,30			SubstitutionWrapper) else SubstitutionWrapper(substitutions)31		self.includeDirs = includeDirs32		# Indent multiline substitution blocks to mmaatch the start of the block.33		self.indent = indent34		self.indentRegexpr = re.compile(r"(?:^|\n)([ \t]*)$")35		# Used to trigger the else condition, this works as any un-resolved if must be followed by the else (if any).36		self.followElse = False37	def visitBegin(self, result: ResultType) -> ResultType:38		return []39	def resolveExpressions(self, sequence: Sequence) -> typing.List[typing.Any]:40		"""Resolve expressions into their values.41		Expression is a nested sequence that might correspond to callable arguments, pipeable expression or more42		simply a single expression.43		"""44		values: typing.List[typing.Any] = []45		operator = None46		operatorUnary = None47		def substitute(value: typing.Any, key: typing.Any) -> typing.Any:48			if isinstance(key, str) and hasattr(value, key):49				return getattr(value, key)50			try:51				return value[key]52			except:53				raise Exception(54					f"Substitution value for the key '{key}' does not exists. Value is: '{Error.valueExtract(value)}'")55		operators: typing.Dict[str, typing.Callable[[typing.Any, typing.Any], typing.Any]] = {56			"|": (lambda l, r: r(l)),57			"==": (lambda l, r: l == r),58			"!=": (lambda l, r: l != r),59			">": (lambda l, r: l > r),60			">=": (lambda l, r: l >= r),61			"<": (lambda l, r: l < r),62			"<=": (lambda l, r: l <= r),63			"in": (lambda l, r: l in r),64		}65		operatorsUnary: typing.Dict[str, typing.Callable[[typing.Any], typing.Any]] = {"not": (lambda r: not r)}66		for element in sequence:67			try:68				elementType = element.getAttr("type").value69				if elementType in operators:70					assert operator is None, f"Detected 2 consecutive operators '{operator}' and '{elementType}'."71					operator = elementType72				elif elementType in operatorsUnary:73					assert operatorUnary is None, f"Detected 2 consecutive unary operators '{operatorUnary}' and '{elementType}'."74					operatorUnary = elementType75				else:76					value: typing.Any77					if elementType == "symbol":78						value = self.substitutions79						for symbol in element.getNestedSequenceAssert(kind="symbol"):80							symbolType = symbol.getAttr("type").value if symbol.isAttr("type") else "symbol"81							if symbolType == "symbol":82								key = symbol.getAttr("value").value83								value = substitute(value, key)84							elif symbolType == "callable":85								assert callable(value), f"The value is not callable."86								args = self.resolveExpressions(symbol.getNestedSequenceAssert("callable"))87								value = value(*args)88							elif symbolType == "array":89								key = self.resolveExpression(symbol.getNestedSequenceAssert("array"))90								value = substitute(value, key)91							else:92								assert False, f"Unknwon symbol type '{symbolType}'."93					elif elementType == "string":94						value = element.getAttr("value").value95					elif elementType == "number":96						value = float(element.getAttr("value").value)97					elif elementType == "true":98						value = True99					elif elementType == "false":100						value = False101					else:102						assert False, f"Unsupported element type '{elementType}'."103					if operator is not None:104						assert len(values) > 0, "There is no value to apply this {operator} operator."105						values[-1] = operators[operator](values[-1], value)106						operator = None107					elif operatorUnary is not None:108						value = operatorsUnary[operatorUnary](value)109						values.append(value)110						operatorUnary = None111					else:112						values.append(value)113			except Exception as e:114				Error.handleFromElement(element=element, message=str(e))115		assert operator is None and operatorUnary is None, "Unterminated expression."116		return values117	def resolveExpression(self, sequence: Sequence) -> typing.Any:118		"""Resolve a single expression and ensure it is unique."""119		values = self.resolveExpressions(sequence)120		assert len(values) == 1, f"There are more than a single value: {[type(v) for v in values]}."121		return values[0]122	def visitSubstitution(self, element: Element, result: ResultType) -> None:123		"""124		Handle substitution.125		"""126		value = self.resolveExpression(element.getNestedSequenceAssert("value"))127		# Save the output128		assert isinstance(value,129			(int, float, str, pathlib.Path130				)), f"The resulting substitued value must be a number, a string or a path, instead received {type(value)}."131		self.appendSubstitution(element=element, result=result, string=str(value))132	def appendSubstitution(self, element: Element, result: ResultType, string: str) -> ResultType:133		# Apply indentation if enabled134		if self.indent and result:135			m = self.indentRegexpr.search(result[-1])136			if m:137				string = string.replace("\n", "\n" + m.group(1))138		result.append(string)139		return result140	def appendBlock(self, element: Element, result: ResultType, block: ResultType) -> ResultType:141		result += block142		return result143	def visitForBlock(self, element: Element) -> ResultType:144		"""145		Handle for loop block.146		"""147		Error.assertHasAttr(element=element, attr="value1")148		Error.assertHasSequence(element=element, sequence="iterable")149		Error.assertHasSequence(element=element, sequence="nested")150		value1 = element.getAttr("value1").value151		value2 = element.getAttrValue("value2")152		sequence = element.getNestedSequence(kind="nested")153		assert sequence154		block: ResultType = []155		# Loop through the elements156		iterable = self.resolveExpression(sequence=element.getNestedSequenceAssert("iterable"))157		loop = Loop(self.substitutions["loop"] if "loop" in self.substitutions else None)158		self.substitutions.register(element=element, key="loop", value=loop)159		if value2 is None:160			for value in iterable:161				self.substitutions.register(element=element, key=value1, value=value)162				block += self._visit(sequence=sequence)163				self.substitutions.unregister(value1)164				loop._inc()165		else:166			iterablePair = iterable.items() if isinstance(iterable, dict) else enumerate(iterable)167			for key, value in iterablePair:168				self.substitutions.register(element=element, key=value1, value=key)169				self.substitutions.register(element=element, key=value2, value=value)170				block += self._visit(sequence=sequence)171				self.substitutions.unregister(value2)172				self.substitutions.unregister(value1)173				loop._inc()174		self.substitutions.unregister("loop")175		return block176	def visitIfBlock(self, element: Element, optionalCondition: bool) -> ResultType:177		"""178		Handle if block.179		"""180		sequence = element.getNestedSequenceAssert(kind="nested")181		maybeCondition = element.getNestedSequence(kind="condition")182		if maybeCondition is None:183			assert optionalCondition, "Missing condition."184			condition = True185		else:186			condition = bool(self.resolveExpression(sequence=maybeCondition))187		self.followElse = not condition188		if condition:189			return self._visit(sequence=sequence)190		return []191	def processMacro(self, element: Element, *args: typing.Any) -> str:192		"""193		Process a macro already defined.194		"""195		sequence = element.getNestedSequence("nested")196		assert sequence197		# Build the argument list198		argList = []199		argument = element.getNestedSequence("argument")200		assert argument is not None201		for arg in argument:202			Error.assertHasAttr(element=arg, attr="name")203			argList.append(arg.getAttr("name").value)204		# Sanity check205		Error.assertTrue(element=element,206			condition=len(argList) == len(args),207			message="Wrong number of argument(s), expected {}: {}".format(len(argList), ", ".join(argList)))208		for i, name in enumerate(argList):209			self.substitutions.register(element=element, key=name, value=args[i])210		# Process the template211		result = self._visit(sequence=sequence)212		for name in argList:213			self.substitutions.unregister(name)214		return "".join(result)215	def visitMacro(self, element: Element) -> None:216		"""217		Handle macro definition block.218		"""219		Error.assertHasSequence(element=element, sequence="argument")220		Error.assertHasSequence(element=element, sequence="nested")221		Error.assertHasAttr(element=element, attr="name")222		name = element.getAttr("name").value223		Error.assertTrue(element=element,224			attr="name",225			condition=(name not in self.substitutions),226			message="Name conflict with macro and an already existing name: '{}'.".format(name))227		# Register the macro228		self.substitutions.register(element=element, key=name, value=lambda *args: self.processMacro(element, *args))229	def visitInclude(self, element: Element) -> ResultType:230		"""231		Handle include.232		"""233		Error.assertHasAttr(element=element, attr="value")234		includePathStr = element.getAttr("value").value235		Error.assertTrue(element=element,236			condition=isinstance(includePathStr, str),237			message="The include path must resolve into a string, instead: '{}'.".format(includePathStr))238		path = pathlib.Path(includePathStr)239		paths = [(base / path) for base in self.includeDirs if (base / path).is_file()]240		Error.assertTrue(element=element,241			condition=len(paths) > 0,242			message="No valid file '{}' within {}".format(includePathStr,243			str([f.as_posix() for f in self.includeDirs])))244		template = bzd.template.template.Template(template=paths[0].read_text(),245			includeDirs=self.includeDirs,246			indent=self.indent)247		result, substitutions = template._render(substitutions=self.substitutions)248		# Update the current substitution object249		self.substitutions.update(substitutions)250		return result251	def visitElement(self, element: Element, result: ResultType) -> ResultType:252		"""253		Go through all elements and dispatch the action.254		"""255		Error.assertHasAttr(element=element, attr="category")256		category = element.getAttr("category").value257		try:258			# Raw content259			if category == "content":260				Error.assertHasAttr(element=element, attr="content")261				string = element.getAttr("content").value262				result.append(string)263			# Substitution264			elif category == "substitution":265				self.visitSubstitution(element=element, result=result)266			# Comments267			elif category == "comment":268				pass269			# End statement270			elif category == "end":271				# Reset the else flag here to make sure nested if without else do not trigger.272				self.followElse = False273			# For loop block274			elif category == "for":275				block = self.visitForBlock(element=element)276				self.appendBlock(element=element, result=result, block=block)277			# If block278			elif category == "if":279				block = self.visitIfBlock(element=element, optionalCondition=False)280				self.appendBlock(element=element, result=result, block=block)281			# Else block282			elif category == "else":283				block = []284				if self.followElse:285					block = self.visitIfBlock(element=element, optionalCondition=True)286				self.appendBlock(element=element, result=result, block=block)287			# Macro block288			elif category == "macro":289				self.visitMacro(element=element)290			# Include block291			elif category == "include":292				block = self.visitInclude(element=element)293				self.appendBlock(element=element, result=result, block=block)294			else:295				raise Exception("Unsupported category: '{}'.".format(category))296		# Propagate processed exception to the top layer297		except ExceptionParser as e:298			raise e299		except Exception as e:300			Error.handleFromElement(element=element, message=str(e))...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!!
