text: from ruamel.yaml.comments import CommentedSeq, CommentedMap
  from strictyaml.exceptions import YAMLValidationError
  from strictyaml.yamlpointer import YAMLPointer
  from strictyaml import utils
  from copy import deepcopy, copy
  import sys
  
  if sys.version_info[0] == 3:
      unicode = str
  
  
  class YAMLChunk(object):
      """
      Represents a section of the document with references to the ruamel
      parsed document and the strictparsed document.
  
      Most operations done by validators on the document are done using this object.
  
      Before validation the strictparsed document will be identical to the
      ruamelparsed document. After it will contain CommentedMaps, CommentedSeqs
      and YAML objects.
      """
  
      def __init__(
          self,
          ruamelparsed,
          pointer=None,
          label=None,
          strictparsed=None,
          key_association=None,
      ):
          self._ruamelparsed = ruamelparsed
          self._strictparsed = (
              deepcopy(ruamelparsed) if strictparsed is None else strictparsed
          )
          self._pointer = pointer if pointer is not None else YAMLPointer()
          self._label = label
  
          # Associates strictparsed key names with ruamelparsed key names
          # E.g. "my-key-name" -> "My Key name"
          self._key_association = {} if key_association is None else key_association
  
      def expecting_but_found(self, expecting, found=None):
          raise YAMLValidationError(
              expecting,
              found if found is not None else "found {0}".format(self.found()),
              self,
          )
  
      def while_parsing_found(self, what, found=None):
          self.expecting_but_found("while parsing {0}".format(what), found=found)
  
      def process(self, new_item):
          strictparsed = self.pointer.parent().get(self._strictparsed, strictdoc=True)
          current_parsed = (
              strictparsed._value if hasattr(strictparsed, "_value") else strictparsed
          )
  
          def actual_key_from_string_key(string_key):
              if string_key in current_parsed.keys():
                  return string_key
              else:
                  for key in current_parsed.keys():
                      if hasattr(key, "_value"):
                          if key.text == string_key:
                              return key
  
          if self.pointer.is_index():
              current_parsed[self.pointer.last_index] = new_item
          elif self.pointer.is_val():
              current_parsed[
                  actual_key_from_string_key(self.pointer.last_regularkey)
              ] = new_item
          elif self.pointer.is_key():
              key = actual_key_from_string_key(self.pointer.last_regularkey)
              existing_val = current_parsed[key]
              del current_parsed[key]
              current_parsed[new_item] = existing_val
  
      def is_sequence(self):
          return isinstance(self.contents, CommentedSeq)
  
      def is_mapping(self):
          return isinstance(self.contents, CommentedMap)
  
      def is_scalar(self):
          return not isinstance(self.contents, (CommentedMap, CommentedSeq))
  
      def found(self):
          if self.is_sequence():
              return u"a sequence"
          elif self.is_mapping():
              return u"a mapping"
          elif self.contents == u"":
              return u"a blank string"
          elif utils.is_integer(self.contents):
              return u"an arbitrary integer"
          elif utils.is_decimal(self.contents):
              return u"an arbitrary number"
          else:
              return u"arbitrary text"
  
      def expect_sequence(self, expecting="when expecting a sequence"):
          if not self.is_sequence():
              self.expecting_but_found(expecting, "found {0}".format(self.found()))
          return [self.index(i) for i in range(len(self.contents))]
  
      def expect_mapping(self):
          if not self.is_mapping():
              self.expecting_but_found(
                  "when expecting a mapping", "found {0}".format(self.found())
              )
          return [
              (
                  self.key(regular_key, unicode(validated_key)),
                  self.val(unicode(validated_key)),
              )
              for (regular_key, validated_key) in zip(
                  self.contents.keys(), self.strictparsed().keys()
              )
          ]
  
      def expect_scalar(self, what):
          if not self.is_scalar():
              self.expecting_but_found(
                  "when expecting {0}".format(what), "found {0}".format(self.found())
              )
  
      @property
      def label(self):
          return self._label
  
      @property
      def whole_document(self):
          return self._ruamelparsed
  
      @property
      def pointer(self):
          return self._pointer
  
      def fork(self, strictindex, new_value):
          """
          Return a chunk referring to the same location in a duplicated document.
  
          Used when modifying a YAML chunk so that the modification can be validated
          before changing it.
          """
          forked_chunk = YAMLChunk(
              deepcopy(self._ruamelparsed),
              pointer=self.pointer,
              label=self.label,
              key_association=copy(self._key_association),
          )
          if self.is_scalar():
              # Necessary for e.g. EmptyDict, which reports as a scalar.
              forked_chunk.pointer.set(forked_chunk, "_ruamelparsed", CommentedMap())
              forked_chunk.pointer.set(
                  forked_chunk, "_strictparsed", CommentedMap(), strictdoc=True
              )
          forked_chunk.contents[self.ruamelindex(strictindex)] = new_value.as_marked_up()
          forked_chunk.strictparsed()[strictindex] = deepcopy(new_value.as_marked_up())
          return forked_chunk
  
      def add_key_association(self, unprocessed_key, processed_key):
          self._key_association[processed_key] = unprocessed_key
  
      @property
      def key_association(self):
          return self._key_association
  
      def make_child_of(self, chunk):
          """
          Link one YAML chunk to another.
  
          Used when inserting a chunk of YAML into another chunk.
          """
          if self.is_mapping():
              for key, value in self.contents.items():
                  self.key(key, key).pointer.make_child_of(chunk.pointer)
                  self.val(key).make_child_of(chunk)
          elif self.is_sequence():
              for index, item in enumerate(self.contents):
                  self.index(index).make_child_of(chunk)
          else:
              self.pointer.make_child_of(chunk.pointer)
  
      def _select(self, pointer):
          """
          Get a YAMLChunk referenced by a pointer.
          """
          return YAMLChunk(
              self._ruamelparsed,
              pointer=pointer,
              label=self._label,
              strictparsed=self._strictparsed,
              key_association=copy(self._key_association),
          )
  
      def index(self, strictindex):
          """
          Return a chunk in a sequence referenced by index.
          """
          return self._select(self._pointer.index(self.ruamelindex(strictindex)))
  
      def ruamelindex(self, strictindex):
          """
          Get the ruamel equivalent of a strict parsed index.
  
          E.g. 0 -> 0, 1 -> 2, parsed-via-slugify -> Parsed via slugify
          """
          return (
              self.key_association.get(strictindex, strictindex)
              if self.is_mapping()
              else strictindex
          )
  
      def val(self, strictkey):
          """
          Return a chunk referencing a value in a mapping with the key 'key'.
          """
          ruamelkey = self.ruamelindex(strictkey)
          return self._select(self._pointer.val(ruamelkey, strictkey))
  
      def key(self, key, strictkey=None):
          """
          Return a chunk referencing a key in a mapping with the name 'key'.
          """
          return self._select(self._pointer.key(key, strictkey))
  
      def textslice(self, start, end):
          """
          Return a chunk referencing a slice of a scalar text value.
          """
          return self._select(self._pointer.textslice(start, end))
  
      def start_line(self):
          return self._pointer.start_line(self._ruamelparsed)
  
      def end_line(self):
          return self._pointer.end_line(self._ruamelparsed)
  
      def lines(self):
          return self._pointer.lines(self._ruamelparsed)
  
      def lines_before(self, how_many):
          return self._pointer.lines_before(self._ruamelparsed, how_many)
  
      def lines_after(self, how_many):
          return self._pointer.lines_after(self._ruamelparsed, how_many)
  
      @property
      def contents(self):
          return self._pointer.get(self._ruamelparsed)
  
      def strictparsed(self):
          return self._pointer.get(self._strictparsed, strictdoc=True)
  