def process_action_input(cls, context, input):
   input_error = {}
   for key, argument in context.action.arguments.items():
     value_provided = key in input
     if not value_provided and argument._default is not None:
       # this must be here because the default value will be ignored, see line 99
       value_provided = True
       value = argument._default
     else:
       value = input.get(key)
     if argument and hasattr(argument, 'format'):
       try:
         if not value_provided and not argument._required:
           continue # skip the .format only if the value was not provided, and if the argument is not required
         value = argument.format(value)
         if hasattr(argument, '_validator') and argument._validator:  # _validator is a custom function that is available by ndb.
           argument._validator(argument, value)
         context.input[key] = value
       except ndb.PropertyError as e:
         if e.message not in input_error:
           input_error[e.message] = []
         input_error[e.message].append(key)  # We group argument exceptions based on exception messages.
       except Exception as e:
         # If this is not defined it throws an error.
         if 'non_property_error' not in input_error:
           input_error['non_property_error'] = []
         input_error['non_property_error'].append(key)  # Or perhaps, 'non_specific_error', or something simmilar.
         util.logger(e, 'exception')
   if len(input_error):
     raise InputError(input_error)
 def run(cls, input):
   pr = cProfile.Profile()
   pr.enable()
   util.logger('Payload: %s' % input)
   context = Context()
   cls.process_blob_input(context, input)  # This is the most efficient strategy to handle blobs we can think of!
   try:
     cls.init()
     cls.get_models(context)
     cls.get_model(context, input)
     cls.get_action(context, input)
     cls.process_action_input(context, input)
     cls.execute_action(context, input)
   except Exception as e:
     throw = True
     if isinstance(e.message, dict):
       # Here we handle our exceptions.
       for key, value in e.message.items():
         context.error(key, value)
         throw = False
     if isinstance(e, datastore_errors.Timeout):
       context.error('transaction', 'timeout')
       throw = False
     if isinstance(e, datastore_errors.TransactionFailedError):
       context.error('transaction', 'failed')
       throw = False
     if throw:
       raise  # Here we raise all other unhandled exceptions!
   finally:
     cls.process_blob_output(context)  # This is the most efficient strategy to handle blobs we can think of!
     pr.disable()
     s = StringIO.StringIO()
     sortby = 'cumulative'
     ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
     ps.print_stats()
     log = s.getvalue()
     class PerformanceLog(ndb.BaseModel):
       log = ndb.TextProperty()
       
     PerformanceLog(log=log, id='endpoint.action.%s' % context.action.key.id()).put()
   return context.output
 def execute_action(cls, context, input):
   util.logger('Execute action: %s.%s' % (context.model.__name__, context))
   util.logger('Arguments: %s' % (context.input))
   def execute_plugins(plugins):
     for plugin in plugins:
       util.logger('Running plugin: %s.%s' % (plugin.__module__, plugin.__class__.__name__))
       plugin.run(context)
   if hasattr(context.model, 'get_plugin_groups') and callable(context.model.get_plugin_groups):
     try:
       plugin_groups = context.model.get_plugin_groups(context.action)
       if len(plugin_groups):
         for group in plugin_groups:
           if len(group.plugins):
             if group.transactional:
               ndb.transaction(lambda: execute_plugins(group.plugins), xg=True)
             else:
               execute_plugins(group.plugins)
     except event.TerminateAction as e:
       pass
     except Exception as e:
       raise
 def process_blob_output(cls, context):
   if len(context.blob_unused):
     util.logger('DELETED BLOBS: %s' % [str(b) for b in context.blob_unused])
     blobstore.delete(context.blob_unused)
     context.blob_unused = []
 def execute_plugins(plugins):
   for plugin in plugins:
     util.logger('Running plugin: %s.%s' % (plugin.__module__, plugin.__class__.__name__))
     plugin.run(context)