HEX
Server: Apache/2.4.65 (Ubuntu)
System: Linux ielts-store-v2 6.8.0-1036-gcp #38~22.04.1-Ubuntu SMP Thu Aug 14 01:19:18 UTC 2025 x86_64
User: root (0)
PHP: 7.2.34-54+ubuntu20.04.1+deb.sury.org+1
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,
Upload Files
File: //snap/google-cloud-cli/396/lib/googlecloudsdk/appengine/tools/dispatch_xml_parser.py
# Copyright 2016 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# -*- coding: utf-8 -*- #
"""Directly processes text of dispatch.xml.

DispatchXmlParser is called with an XML string to produce a list of
DispatchEntry objects containing the data from the XML.
"""

from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

from xml.etree import ElementTree

from googlecloudsdk.appengine.tools import xml_parser_utils
from googlecloudsdk.appengine.tools.app_engine_config_exception import AppEngineConfigException

MISSING_URL = '<dispatch> node must contain a <url>'
MISSING_MODULE = '<dispatch> node must contain a <module>'


def GetDispatchYaml(application, dispatch_xml_str):
  return _MakeDispatchListIntoYaml(
      application, DispatchXmlParser().ProcessXml(dispatch_xml_str))


def _MakeDispatchListIntoYaml(application, dispatch_list):
  """Converts list of DispatchEntry objects into a YAML string."""
  statements = []
  if application:
    statements.append('application: %s' % application)
  statements.append('dispatch:')
  for entry in dispatch_list:
    statements += entry.ToYaml()
  return '\n'.join(statements) + '\n'


class DispatchXmlParser(object):
  """Provides logic for walking down XML tree and pulling data."""

  def ProcessXml(self, xml_str):
    """Parses XML string and returns object representation of relevant info.

    Args:
      xml_str: The XML string.
    Returns:
      A list of DispatchEntry objects defining how URLs are dispatched to
      modules.
    Raises:
      AppEngineConfigException: In case of malformed XML or illegal inputs.
    """

    try:
      self.dispatch_entries = []
      self.errors = []
      xml_root = ElementTree.fromstring(xml_str)
      if xml_root.tag != 'dispatch-entries':
        raise AppEngineConfigException('Root tag must be <dispatch-entries>')

      for child in list(xml_root):
        self.ProcessDispatchNode(child)

      if self.errors:
        raise AppEngineConfigException('\n'.join(self.errors))

      return self.dispatch_entries
    except ElementTree.ParseError:
      raise AppEngineConfigException('Bad input -- not valid XML')

  def ProcessDispatchNode(self, node):
    """Processes XML <dispatch> nodes into DispatchEntry objects.

    The following information is parsed out:
      url: The URL or URL pattern to route.
      module: The module to route it to.
    If there are no errors, the data is loaded into a DispatchEntry object
    and added to a list. Upon error, a description of the error is added to
    a list and the method terminates.

    Args:
      node: <dispatch> XML node in dos.xml.
    """
    tag = xml_parser_utils.GetTag(node)
    if tag != 'dispatch':
      self.errors.append('Unrecognized node: <%s>' % tag)
      return

    entry = DispatchEntry()
    entry.url = xml_parser_utils.GetChildNodeText(node, 'url')
    entry.module = xml_parser_utils.GetChildNodeText(node, 'module')

    validation = self._ValidateEntry(entry)
    if validation:
      self.errors.append(validation)
      return
    self.dispatch_entries.append(entry)

  def _ValidateEntry(self, entry):
    if not entry.url:
      return MISSING_URL
    if not entry.module:
      return MISSING_MODULE


class DispatchEntry(object):
  """Instances contain information about individual dispatch entries."""

  def ToYaml(self):
    return [
        "- url: '%s'" % self._SanitizeForYaml(self.url),
        '  module: %s' % self.module,
    ]

  def _SanitizeForYaml(self, dirty_str):
    return dirty_str.replace("'", r"\'")