thirdparty/google_appengine/google/appengine/api/appinfo.py
changeset 2864 2e0b0af889be
parent 2273 e4cb9c53db3e
child 3031 7678f72140e6
--- a/thirdparty/google_appengine/google/appengine/api/appinfo.py	Sat Sep 05 14:04:24 2009 +0200
+++ b/thirdparty/google_appengine/google/appengine/api/appinfo.py	Sun Sep 06 23:31:53 2009 +0200
@@ -15,7 +15,7 @@
 # limitations under the License.
 #
 
-"""AppInfo tools
+"""AppInfo tools.
 
 Library for working with AppInfo records in memory, store and load from
 configuration files.
@@ -29,8 +29,8 @@
 
 from google.appengine.api import appinfo_errors
 from google.appengine.api import validation
+from google.appengine.api import yaml_builder
 from google.appengine.api import yaml_listener
-from google.appengine.api import yaml_builder
 from google.appengine.api import yaml_object
 
 
@@ -40,11 +40,13 @@
 _DELTA_REGEX = r'([1-9][0-9]*)([DdHhMm]|[sS]?)'
 _EXPIRATION_REGEX = r'\s*(%s)(\s+%s)*\s*' % (_DELTA_REGEX, _DELTA_REGEX)
 
+_SERVICE_RE_STRING = r'(mail|xmpp_message)'
+
 _EXPIRATION_CONVERSIONS = {
-  'd': 60 * 60 * 24,
-  'h': 60 * 60,
-  'm': 60,
-  's': 1,
+    'd': 60 * 60 * 24,
+    'h': 60 * 60,
+    'm': 60,
+    's': 1,
 }
 
 APP_ID_MAX_LEN = 100
@@ -72,17 +74,17 @@
 
 REQUIRE_MATCHING_FILE = 'require_matching_file'
 
-DEFAULT_SKIP_FILES = (r"^(.*/)?("
-                      r"(app\.yaml)|"
-                      r"(app\.yml)|"
-                      r"(index\.yaml)|"
-                      r"(index\.yml)|"
-                      r"(#.*#)|"
-                      r"(.*~)|"
-                      r"(.*\.py[co])|"
-                      r"(.*/RCS/.*)|"
-                      r"(\..*)|"
-                      r")$")
+DEFAULT_SKIP_FILES = (r'^(.*/)?('
+                      r'(app\.yaml)|'
+                      r'(app\.yml)|'
+                      r'(index\.yaml)|'
+                      r'(index\.yml)|'
+                      r'(#.*#)|'
+                      r'(.*~)|'
+                      r'(.*\.py[co])|'
+                      r'(.*/RCS/.*)|'
+                      r'(\..*)|'
+                      r')$')
 
 LOGIN = 'login'
 SECURE = 'secure'
@@ -101,6 +103,7 @@
 HANDLERS = 'handlers'
 DEFAULT_EXPIRATION = 'default_expiration'
 SKIP_FILES = 'skip_files'
+SERVICES = 'inbound_services'
 
 
 class URLMap(validation.Validated):
@@ -176,42 +179,42 @@
 
   ATTRIBUTES = {
 
-    URL: validation.Optional(_URL_REGEX),
-    LOGIN: validation.Options(LOGIN_OPTIONAL,
-                              LOGIN_REQUIRED,
-                              LOGIN_ADMIN,
-                              default=LOGIN_OPTIONAL),
+      URL: validation.Optional(_URL_REGEX),
+      LOGIN: validation.Options(LOGIN_OPTIONAL,
+                                LOGIN_REQUIRED,
+                                LOGIN_ADMIN,
+                                default=LOGIN_OPTIONAL),
 
-    SECURE: validation.Options(SECURE_HTTP,
-                               SECURE_HTTPS,
-                               SECURE_HTTP_OR_HTTPS,
-                               default=SECURE_HTTP),
+      SECURE: validation.Options(SECURE_HTTP,
+                                 SECURE_HTTPS,
+                                 SECURE_HTTP_OR_HTTPS,
+                                 default=SECURE_HTTP),
 
 
 
-    HANDLER_STATIC_FILES: validation.Optional(_FILES_REGEX),
-    UPLOAD: validation.Optional(_FILES_REGEX),
+      HANDLER_STATIC_FILES: validation.Optional(_FILES_REGEX),
+      UPLOAD: validation.Optional(_FILES_REGEX),
 
 
-    HANDLER_STATIC_DIR: validation.Optional(_FILES_REGEX),
+      HANDLER_STATIC_DIR: validation.Optional(_FILES_REGEX),
 
 
-    MIME_TYPE: validation.Optional(str),
-    EXPIRATION: validation.Optional(_EXPIRATION_REGEX),
+      MIME_TYPE: validation.Optional(str),
+      EXPIRATION: validation.Optional(_EXPIRATION_REGEX),
 
 
-    HANDLER_SCRIPT: validation.Optional(_FILES_REGEX),
+      HANDLER_SCRIPT: validation.Optional(_FILES_REGEX),
 
-    REQUIRE_MATCHING_FILE: validation.Optional(bool),
+      REQUIRE_MATCHING_FILE: validation.Optional(bool),
   }
 
   COMMON_FIELDS = set([URL, LOGIN, SECURE])
 
   ALLOWED_FIELDS = {
-    HANDLER_STATIC_FILES: (MIME_TYPE, UPLOAD, EXPIRATION,
-                           REQUIRE_MATCHING_FILE),
-    HANDLER_STATIC_DIR: (MIME_TYPE, EXPIRATION, REQUIRE_MATCHING_FILE),
-    HANDLER_SCRIPT: (),
+      HANDLER_STATIC_FILES: (MIME_TYPE, UPLOAD, EXPIRATION,
+                             REQUIRE_MATCHING_FILE),
+      HANDLER_STATIC_DIR: (MIME_TYPE, EXPIRATION, REQUIRE_MATCHING_FILE),
+      HANDLER_SCRIPT: (),
   }
 
   def GetHandler(self):
@@ -253,9 +256,9 @@
           not (attribute in allowed_fields or
                attribute in URLMap.COMMON_FIELDS or
                attribute == mapping_type)):
-            raise appinfo_errors.UnexpectedHandlerAttribute(
-                'Unexpected attribute "%s" for mapping type %s.' %
-                (attribute, mapping_type))
+        raise appinfo_errors.UnexpectedHandlerAttribute(
+            'Unexpected attribute "%s" for mapping type %s.' %
+            (attribute, mapping_type))
 
     if mapping_type == HANDLER_STATIC_FILES and not self.upload:
       raise appinfo_errors.MissingHandlerAttribute(
@@ -309,15 +312,18 @@
   ATTRIBUTES = {
 
 
-    APPLICATION: APPLICATION_RE_STRING,
-    VERSION: VERSION_RE_STRING,
-    RUNTIME: RUNTIME_RE_STRING,
+      APPLICATION: APPLICATION_RE_STRING,
+      VERSION: VERSION_RE_STRING,
+      RUNTIME: RUNTIME_RE_STRING,
 
 
-    API_VERSION: API_VERSION_RE_STRING,
-    HANDLERS: validation.Optional(validation.Repeated(URLMap)),
-    DEFAULT_EXPIRATION: validation.Optional(_EXPIRATION_REGEX),
-    SKIP_FILES: validation.RegexStr(default=DEFAULT_SKIP_FILES)
+      API_VERSION: API_VERSION_RE_STRING,
+      HANDLERS: validation.Optional(validation.Repeated(URLMap)),
+
+      SERVICES: validation.Optional(validation.Repeated(
+          validation.Regex(_SERVICE_RE_STRING))),
+      DEFAULT_EXPIRATION: validation.Optional(_EXPIRATION_REGEX),
+      SKIP_FILES: validation.RegexStr(default=DEFAULT_SKIP_FILES)
   }
 
   def CheckInitialized(self):
@@ -349,8 +355,9 @@
     An instance of AppInfoExternal as loaded from a YAML file.
 
   Raises:
-    EmptyConfigurationFile when there are no documents in YAML file.
-    MultipleConfigurationFile when there is more than one document in YAML
+    ValueError: if a specified service is not valid.
+    EmptyConfigurationFile: when there are no documents in YAML file.
+    MultipleConfigurationFile: when there is more than one document in YAML
     file.
   """
   builder = yaml_object.ObjectBuilder(AppInfoExternal)
@@ -386,7 +393,7 @@
 
 _file_path_positive_re = re.compile(r'^[ 0-9a-zA-Z\._\+/\$-]{1,256}$')
 
-_file_path_negative_1_re = re.compile(r'\.\.|^\./|\.$|/\./|^-')
+_file_path_negative_1_re = re.compile(r'\.\.|^\./|\.$|/\./|^-|^_ah/')
 
 _file_path_negative_2_re = re.compile(r'//|/$')
 
@@ -413,7 +420,8 @@
   if _file_path_positive_re.match(filename) is None:
     return 'Invalid character in filename: %s' % filename
   if _file_path_negative_1_re.search(filename) is not None:
-    return ('Filename cannot contain "." or ".." or start with "-": %s' %
+    return ('Filename cannot contain "." or ".." '
+            'or start with "-" or "_ah/": %s' %
             filename)
   if _file_path_negative_2_re.search(filename) is not None:
     return 'Filename cannot have trailing / or contain //: %s' % filename