#!/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.
#




"""PyYAML event listener

Contains class which interprets YAML events and forwards them to
a handler object.
"""



from google.appengine.api import yaml_errors
import yaml



_EVENT_METHOD_MAP = {
  yaml.events.StreamStartEvent: 'StreamStart',
  yaml.events.StreamEndEvent: 'StreamEnd',
  yaml.events.DocumentStartEvent: 'DocumentStart',
  yaml.events.DocumentEndEvent: 'DocumentEnd',
  yaml.events.AliasEvent: 'Alias',
  yaml.events.ScalarEvent: 'Scalar',
  yaml.events.SequenceStartEvent: 'SequenceStart',
  yaml.events.SequenceEndEvent: 'SequenceEnd',
  yaml.events.MappingStartEvent: 'MappingStart',
  yaml.events.MappingEndEvent: 'MappingEnd',
}


class EventHandler(object):
  """Handler interface for parsing YAML files.

  Implement this interface to define specific YAML event handling class.
  Implementing classes instances are passed to the constructor of
  EventListener to act as a receiver of YAML parse events.
  """
  def StreamStart(self, event, loader):
    """Handle start of stream event"""

  def StreamEnd(self, event, loader):
    """Handle end of stream event"""

  def DocumentStart(self, event, loader):
    """Handle start of document event"""

  def DocumentEnd(self, event, loader):
    """Handle end of document event"""

  def Alias(self, event, loader):
    """Handle alias event"""

  def Scalar(self, event, loader):
    """Handle scalar event"""

  def SequenceStart(self, event, loader):
    """Handle start of sequence event"""

  def SequenceEnd(self, event, loader):
    """Handle end of sequence event"""

  def MappingStart(self, event, loader):
    """Handle start of mappping event"""

  def MappingEnd(self, event, loader):
    """Handle end of mapping event"""


class EventListener(object):
  """Helper class to re-map PyYAML events to method calls.

  By default, PyYAML generates its events via a Python generator.  This class
  is a helper that iterates over the events from the PyYAML parser and forwards
  them to a handle class in the form of method calls.  For simplicity, the
  underlying event is forwarded to the handler as a parameter to the call.

  This object does not itself produce iterable objects, but is really a mapping
  to a given handler instance.

    Example use:

      class PrintDocumentHandler(object):
        def DocumentStart(event):
          print "A new document has been started"

      EventListener(PrintDocumentHandler()).Parse('''
        key1: value1
        ---
        key2: value2
        '''

      >>> A new document has been started
          A new document has been started

  In the example above, the implemented handler class (PrintDocumentHandler)
  has a single method which reports each time a new document is started within
  a YAML file.  It is not necessary to subclass the EventListener, merely it
  receives a PrintDocumentHandler instance.  Every time a new document begins,
  PrintDocumentHandler.DocumentStart is called with the PyYAML event passed
  in as its parameter..
  """

  def __init__(self, event_handler):
    """Initialize PyYAML event listener.

    Constructs internal mapping directly from event type to method on actual
    handler.  This prevents reflection being used during actual parse time.

    Args:
      event_handler: Event handler that will receive mapped events. Must
        implement at least one appropriate handler method named from
        the values of the _EVENT_METHOD_MAP.

    Raises:
      ListenerConfigurationError if event_handler is not an EventHandler.
    """
    if not isinstance(event_handler, EventHandler):
      raise yaml_errors.ListenerConfigurationError(
        'Must provide event handler of type yaml_listener.EventHandler')
    self._event_method_map = {}

    for event, method in _EVENT_METHOD_MAP.iteritems():

      self._event_method_map[event] = getattr(event_handler, method)

  def HandleEvent(self, event, loader=None):
    """Handle individual PyYAML event.

    Args:
      event: Event to forward to method call in method call.

    Raises:
      IllegalEvent when receives an unrecognized or unsupported event type.
    """

    if event.__class__ not in _EVENT_METHOD_MAP:
      raise yaml_errors.IllegalEvent(
            "%s is not a valid PyYAML class" % event.__class__.__name__)

    if event.__class__ in self._event_method_map:
      self._event_method_map[event.__class__](event, loader)

  def _HandleEvents(self, events):
    """Iterate over all events and send them to handler.

    This method is not meant to be called from the interface.

    Only use in tests.

    Args:
      events: Iterator or generator containing events to process.
    raises:
      EventListenerParserError when a yaml.parser.ParserError is raised.
      EventError when an exception occurs during the handling of an event.
    """
    for event in events:
      try:
        self.HandleEvent(*event)
      except Exception, e:
        event_object, loader = event
        raise yaml_errors.EventError(e, event_object)

  def _GenerateEventParameters(self,
                               stream,
                               loader_class=yaml.loader.SafeLoader):
    """Creates a generator that yields event, loader parameter pairs.

    For use as parameters to HandleEvent method for use by Parse method.
    During testing, _GenerateEventParameters is simulated by allowing
    the harness to pass in a list of pairs as the parameter.

    A list of (event, loader) pairs must be passed to _HandleEvents otherwise
    it is not possible to pass the loader instance to the handler.

    Also responsible for instantiating the loader from the Loader
    parameter.

    Args:
      stream: String document or open file object to process as per the
        yaml.parse method.  Any object that implements a 'read()' method which
        returns a string document will work.
      Loader: Loader class to use as per the yaml.parse method.  Used to
        instantiate new yaml.loader instance.

    Yields:
      Tuple(event, loader) where:
        event: Event emitted by PyYAML loader.
        loader_class: Used for dependency injection.
    """
    assert loader_class is not None
    try:
      loader = loader_class(stream)
      while loader.check_event():
        yield (loader.get_event(), loader)
    except yaml.error.YAMLError, e:
      raise yaml_errors.EventListenerYAMLError(e)

  def Parse(self, stream, loader_class=yaml.loader.SafeLoader):
    """Call YAML parser to generate and handle all events.

    Calls PyYAML parser and sends resulting generator to handle_event method
    for processing.

    Args:
      stream: String document or open file object to process as per the
        yaml.parse method.  Any object that implements a 'read()' method which
        returns a string document will work with the YAML parser.
      loader_class: Used for dependency injection.
    """
    self._HandleEvents(self._GenerateEventParameters(stream, loader_class))
