[{
"type": "thumb-down",
"id": "hardToUnderstand",
"label":"Hard to understand"
},{
"type": "thumb-down",
"id": "incorrectInformationOrSampleCode",
"label":"Incorrect information or sample code"
},{
"type": "thumb-down",
"id": "missingTheInformationSamplesINeed",
"label":"Missing the information/samples I need"
},{
"type": "thumb-down",
"id": "otherDown",
"label":"Other"
}]
[{
"type": "thumb-up",
"id": "easyToUnderstand",
"label":"Easy to understand"
},{
"type": "thumb-up",
"id": "solvedMyProblem",
"label":"Solved my problem"
},{
"type": "thumb-up",
"id": "otherUp",
"label":"Other"
}]
Source code for google.appengine.api.dispatchinfo
#!/usr/bin/env python## Copyright 2007 Google Inc.## 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.#"""Dispatch configuration tools.Library for parsing dispatch.yaml files and working with these in memory."""from__future__importabsolute_importfrom__future__importunicode_literalsimportosimportrefromgoogle.appengine._internalimportsix_subsetifos.environ.get('APPENGINE_RUNTIME')=='python27':fromgoogle.appengine.apiimportappinfofromgoogle.appengine.apiimportvalidationfromgoogle.appengine.apiimportyaml_builderfromgoogle.appengine.apiimportyaml_listenerfromgoogle.appengine.apiimportyaml_objectelse:fromgoogle.appengine.apiimportappinfofromgoogle.appengine.apiimportvalidationfromgoogle.appengine.apiimportyaml_builderfromgoogle.appengine.apiimportyaml_listenerfromgoogle.appengine.apiimportyaml_object_URL_SPLITTER_RE=re.compile(r'^([^/]+)(/.*)$')_URL_HOST_EXACT_PATTERN_RE=re.compile(r"""# 0 or more . terminated hostname segments (may not start or end in -).^([a-z0-9]([a-z0-9\-]*[a-z0-9])*\.)*# followed by a host name segment.([a-z0-9]([a-z0-9\-]*[a-z0-9])*)$""",re.VERBOSE)_URL_IP_V4_ADDR_RE=re.compile(r"""#4 1-3 digit numbers separated by .^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$""",re.VERBOSE)_URL_HOST_SUFFIX_PATTERN_RE=re.compile(r"""# Single star or^([*]|# Host prefix with no ., Ex '*-a' or[*][a-z0-9\-]*[a-z0-9]|# Host prefix with ., Ex '*-a.b-c.d'[*](\.|[a-z0-9\-]*[a-z0-9]\.)([a-z0-9]([a-z0-9\-]*[a-z0-9])*\.)*([a-z0-9]([a-z0-9\-]*[a-z0-9])*))$""",re.VERBOSE)APPLICATION='application'DISPATCH='dispatch'URL='url'MODULE='module'SERVICE='service'
[docs]classError(Exception):"""Base class for errors in this module."""
[docs]classMalformedDispatchConfigurationError(Error):"""Configuration file for dispatch is malformed."""
[docs]classDispatchEntryURLValidator(validation.Validator):"""Validater for URL patterns."""
[docs]defValidate(self,value,unused_key=None):"""Validates an URL pattern."""ifvalueisNone:raisevalidation.MissingAttribute('url must be specified')ifnotisinstance(value,six_subset.string_types):raisevalidation.ValidationError('url must be a string, not \'%r\''%type(value))url_holder=ParsedURL(value)ifurl_holder.host_exact:_ValidateMatch(_URL_HOST_EXACT_PATTERN_RE,url_holder.host,'invalid host_pattern \'%s\''%url_holder.host)_ValidateNotIpV4Address(url_holder.host)else:_ValidateMatch(_URL_HOST_SUFFIX_PATTERN_RE,url_holder.host_pattern,'invalid host_pattern \'%s\''%url_holder.host_pattern)returnvalue
[docs]classParsedURL(object):"""Dispath Entry URL holder class. Attributes: host_pattern: The host pattern component of the URL pattern. host_exact: True if the host pattern does not start with a *. host: host_pattern with any leading * removed. path_pattern: The path pattern component of the URL pattern. path_exact: True if the path_pattern does not end with a *. path: path_pattern with any trailing * removed. """def__init__(self,url_pattern):"""Initializes this ParsedURL with an URL pattern value. Args: url_pattern: An URL pattern that conforms to the regular expression '^([^/]+)(/.*)$'. Raises: validation.ValidationError: When url_pattern does not match the required regular expression. """split_matcher=_ValidateMatch(_URL_SPLITTER_RE,url_pattern,'invalid url \'%s\''%url_pattern)self.host_pattern,self.path_pattern=split_matcher.groups()ifself.host_pattern.startswith('*'):self.host_exact=Falseself.host=self.host_pattern[1:]else:self.host_exact=Trueself.host=self.host_patternifself.path_pattern.endswith('*'):self.path_exact=Falseself.path=self.path_pattern[:-1]else:self.path_exact=Trueself.path=self.path_pattern
def_ValidateMatch(regex,value,message):"""Validate value matches regex."""matcher=regex.match(value)ifnotmatcher:raisevalidation.ValidationError(message)returnmatcherdef_ValidateNotIpV4Address(host):"""Validate host is not an IPV4 address."""matcher=_URL_IP_V4_ADDR_RE.match(host)ifmatcherandsum(1forxinmatcher.groups()ifint(x)<=255)==4:raisevalidation.ValidationError('Host may not match an ipv4 address \'%s\''%host)returnmatcher
[docs]classDispatchEntry(validation.Validated):"""A Dispatch entry describes a mapping from a URL pattern to a module."""ATTRIBUTES={URL:DispatchEntryURLValidator(),MODULE:validation.Optional(appinfo.MODULE_ID_RE_STRING),SERVICE:validation.Optional(appinfo.MODULE_ID_RE_STRING)}
[docs]classDispatchInfoExternal(validation.Validated):"""Describes the format of a dispatch.yaml file."""ATTRIBUTES={APPLICATION:validation.Optional(appinfo.APPLICATION_RE_STRING),DISPATCH:validation.Optional(validation.Repeated(DispatchEntry)),}
[docs]defLoadSingleDispatch(dispatch_info,open_fn=None):"""Load a dispatch.yaml file or string and return a DispatchInfoExternal. Args: dispatch_info: The contents of a dispatch.yaml file as a string, or an open file object. open_fn: Function for opening files. Unused here, needed to provide a polymorphic API used by appcfg.py yaml parsing. Returns: A DispatchInfoExternal instance which represents the contents of the parsed yaml file. Raises: MalformedDispatchConfigurationError: The yaml file contains multiple dispatch sections or is missing a required value. yaml_errors.EventError: An error occured while parsing the yaml file. """builder=yaml_object.ObjectBuilder(DispatchInfoExternal)handler=yaml_builder.BuilderHandler(builder)listener=yaml_listener.EventListener(handler)listener.Parse(dispatch_info)parsed_yaml=handler.GetResults()ifnotparsed_yaml:returnDispatchInfoExternal()iflen(parsed_yaml)>1:raiseMalformedDispatchConfigurationError('Multiple dispatch: sections ''in configuration.')dispatch_info_external=parsed_yaml[0]fordispatchingetattr(dispatch_info_external,DISPATCH)or[]:ifdispatch.moduleanddispatch.service:raiseMalformedDispatchConfigurationError('Both module: and service: in dispatch entry. Please use only one.')ifnot(dispatch.moduleordispatch.service):raiseMalformedDispatchConfigurationError("Missing required value 'service'.")dispatch.module=dispatch.moduleordispatch.servicedispatch.service=Nonereturndispatch_info_external
[{
"type": "thumb-down",
"id": "hardToUnderstand",
"label":"Hard to understand"
},{
"type": "thumb-down",
"id": "incorrectInformationOrSampleCode",
"label":"Incorrect information or sample code"
},{
"type": "thumb-down",
"id": "missingTheInformationSamplesINeed",
"label":"Missing the information/samples I need"
},{
"type": "thumb-down",
"id": "otherDown",
"label":"Other"
}]
[{
"type": "thumb-up",
"id": "easyToUnderstand",
"label":"Easy to understand"
},{
"type": "thumb-up",
"id": "solvedMyProblem",
"label":"Solved my problem"
},{
"type": "thumb-up",
"id": "otherUp",
"label":"Other"
}]