Load /Users/solydzajs/Desktop/google_appengine into
[Melange.git] / thirdparty / google_appengine / google / appengine / api / croninfo.py
blob0eab26e79b847d3bd655320d9afd99b6d18f0421
1 #!/usr/bin/env python
3 # Copyright 2007 Google Inc.
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
18 """CronInfo tools.
20 A library for working with CronInfo records, describing cron entries for an
21 application. Supports loading the records from yaml.
22 """
26 import logging
27 import sys
28 import traceback
30 try:
31 import pytz
32 except ImportError:
33 pytz = None
35 from google.appengine.cron import groc
36 from google.appengine.api import validation
37 from google.appengine.api import yaml_builder
38 from google.appengine.api import yaml_listener
39 from google.appengine.api import yaml_object
41 _URL_REGEX = r'^/.*$'
42 _TIMEZONE_REGEX = r'^.{0,100}$'
43 _DESCRIPTION_REGEX = r'^.{0,499}$'
46 class GrocValidator(validation.Validator):
47 """Checks that a schedule is in valid groc format."""
49 def Validate(self, value):
50 """Validates a schedule."""
51 if value is None:
52 raise validation.MissingAttribute('schedule must be specified')
53 if not isinstance(value, basestring):
54 raise TypeError('schedule must be a string, not \'%r\''%type(value))
55 schedule = groc.CreateParser(value)
56 try:
57 schedule.timespec()
58 except groc.GrocException, e:
59 raise validation.ValidationError('schedule \'%s\' failed to parse: %s'%(
60 value, e.args[0]))
61 return value
64 class TimezoneValidator(validation.Validator):
65 """Checks that a timezone can be correctly parsed and is known."""
67 def Validate(self, value):
68 """Validates a timezone."""
69 if value is None:
70 return
71 if not isinstance(value, basestring):
72 raise TypeError('timezone must be a string, not \'%r\'' % type(value))
73 if pytz is None:
74 return value
75 try:
76 pytz.timezone(value)
77 except pytz.UnknownTimeZoneError:
78 raise validation.ValidationError('timezone \'%s\' is unknown' % value)
79 except IOError:
80 return value
81 except:
82 unused_e, v, t = sys.exc_info()
83 logging.warning('pytz raised an unexpected error: %s.\n' % (v) +
84 'Traceback:\n' + '\n'.join(traceback.format_tb(t)))
85 raise
86 return value
89 CRON = 'cron'
91 URL = 'url'
92 SCHEDULE = 'schedule'
93 TIMEZONE = 'timezone'
94 DESCRIPTION = 'description'
97 class MalformedCronfigurationFile(Exception):
98 """Configuration file for Cron is malformed."""
99 pass
102 class CronEntry(validation.Validated):
103 """A cron entry describes a single cron job."""
104 ATTRIBUTES = {
105 URL: _URL_REGEX,
106 SCHEDULE: GrocValidator(),
107 TIMEZONE: TimezoneValidator(),
108 DESCRIPTION: validation.Optional(_DESCRIPTION_REGEX)
112 class CronInfoExternal(validation.Validated):
113 """CronInfoExternal describes all cron entries for an application."""
114 ATTRIBUTES = {
115 CRON: validation.Optional(validation.Repeated(CronEntry))
119 def LoadSingleCron(cron_info):
120 """Load a cron.yaml file or string and return a CronInfoExternal object."""
121 builder = yaml_object.ObjectBuilder(CronInfoExternal)
122 handler = yaml_builder.BuilderHandler(builder)
123 listener = yaml_listener.EventListener(handler)
124 listener.Parse(cron_info)
126 cron_info = handler.GetResults()
127 if len(cron_info) < 1:
128 raise MalformedCronfigurationFile('Empty cron configuration.')
129 if len(cron_info) > 1:
130 raise MalformedCronfigurationFile('Multiple cron sections '
131 'in configuration.')
132 return cron_info[0]