from __future__ import absolute_import
import warnings

# Import thirt party modules
import yaml
from yaml.nodes import MappingNode
from yaml.constructor import ConstructorError
try:
    yaml.Loader = yaml.CLoader
    yaml.Dumper = yaml.CDumper
except:
    pass

load = yaml.load


class DuplicateKeyWarning(RuntimeWarning):
    '''
    Warned when duplicate keys exist
    '''

warnings.simplefilter('always', category=DuplicateKeyWarning)


class CustomeConstructor(yaml.constructor.SafeConstructor):
    '''
    Create a custom constructor for manageging YAML
    '''
    def construct_mapping(self, node, deep=False):
        '''
        Build the mapping for yaml
        '''
        if not isinstance(node, MappingNode):
            raise ConstructorError(None, None,
                    'expected a mapping node, but found {0}'.format(node.id),
                    node.start_mark)
        mapping = {}
        for key_node, value_node in node.value:
            key = self.construct_object(key_node, deep=deep)
            try:
                hash(key)
            except TypeError as exc:
                raise ConstructorError('while constructing a mapping', node.start_mark,
                        'found unacceptable key (%s)' % exc, key_node.start_mark)
            value = self.construct_object(value_node, deep=deep)
            if key in mapping:
                warnings.warn(
                    'Duplicate Key: "{0}"'.format(key), DuplicateKeyWarning)
            mapping[key] = value
        return mapping

    def construct_scalar(self, node):
        '''
        Verify integers and pass them in correctly is they are declared as octal
        '''
        if node.tag == 'tag:yaml.org,2002:int':
            if node.value.startswith('0') and not node.value.startswith(('0b', '0x')):
                node.value = node.value.lstrip('0')
        return yaml.constructor.SafeConstructor.construct_scalar(self, node)


class CustomLoader(yaml.reader.Reader, yaml.scanner.Scanner, yaml.parser.Parser,
                   yaml.composer.Composer, CustomeConstructor, yaml.resolver.Resolver):
    def __init__(self, stream):
        yaml.reader.Reader.__init__(self, stream)
        yaml.scanner.Scanner.__init__(self)
        yaml.parser.Parser.__init__(self)
        yaml.composer.Composer.__init__(self)
        CustomeConstructor.__init__(self)
        yaml.resolver.Resolver.__init__(self)

@@ -62,17 +62,17 @@
 ort thir
-t
+d
  party m
@@ -1112,33 +1112,17 @@
     
-raise ConstructorError('w
+err = ('W
 hile
@@ -1148,108 +1148,155 @@
 ping
-', node.start_mark,%0A                        'found unacceptable key (%25s)' %25 exc, key_node.start_mark
+ %7B0%7D found unacceptable '%0A                       'key %7B1%7D').format(node.start_mark, key_node.start_mark)%0A                raise ConstructorError(err
 )%0A  
@@ -1786,16 +1786,38 @@
 ith('0')
+ %5C%0A                   
  and not
@@ -2023,16 +2023,24 @@
 .Reader,
+%0A       
  yaml.sc
@@ -2053,16 +2053,24 @@
 Scanner,
+%0A       
  yaml.pa
@@ -2082,27 +2082,16 @@
 Parser,%0A
-           
         
@@ -2113,16 +2113,24 @@
 omposer,
+%0A       
  Custome
@@ -2141,16 +2141,24 @@
 tructor,
+%0A       
  yaml.re
@@ -2171,24 +2171,246 @@
 .Resolver):%0A
+    '''%0A    Create a custom yaml loader that uses the custom constructor. This allows%0A    for the yaml loading defaults to be manipulated based on needs within salt%0A    to make things like sls file more intuitive.%0A    '''%0A
     def __in

Clean up yaml utils