We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
AWS::Serverless::Api Cors config transform error
#### cfn-lint version:
``` console
$ cfn-lint --version
cfn-lint 0.8.3
```

#### Description of issue:
When I have a `AWS::Serverless::Api` object with a [Cors Configuration](https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#cors-configuration) object in it I routinely get the following error when linting `template.yaml` 

`E0001 Error transforming template: 'dict_node' object has no attribute 'start_mark'`

I also got the following stack trace when running 
```
Traceback (most recent call last):
  File "/usr/local/bin/cfn-lint", line 11, in <module>
    sys.exit(main())
  File "/usr/local/lib/python2.7/site-packages/cfnlint/__main__.py", line 36, in main
    args.regions, args.override_spec))
  File "/usr/local/lib/python2.7/site-packages/cfnlint/core.py", line 46, in run_cli
    return run_checks(filename, template, rules, regions)
  File "/usr/local/lib/python2.7/site-packages/cfnlint/core.py", line 316, in run_checks
    matches.extend(runner.transform())
  File "/usr/local/lib/python2.7/site-packages/cfnlint/__init__.py", line 894, in transform
    matches = transform.transform_template()
  File "/usr/local/lib/python2.7/site-packages/cfnlint/transform.py", line 115, in transform_template
    sam_translator.translate(sam_template=self._template, parameter_values={}))
  File "/Users/eaddingtonwhite/Library/Python/2.7/lib/python/site-packages/samtranslator/translator/translator.py", line 71, in translate
    translated = macro.to_cloudformation(**kwargs)
  File "/Users/eaddingtonwhite/Library/Python/2.7/lib/python/site-packages/samtranslator/model/sam_resources.py", line 501, in to_cloudformation
    rest_api, deployment, stage = api_generator.to_cloudformation()
  File "/Users/eaddingtonwhite/Library/Python/2.7/lib/python/site-packages/samtranslator/model/api/api_generator.py", line 160, in to_cloudformation
    rest_api = self._construct_rest_api()
  File "/Users/eaddingtonwhite/Library/Python/2.7/lib/python/site-packages/samtranslator/model/api/api_generator.py", line 69, in _construct_rest_api
    self._add_cors()
  File "/Users/eaddingtonwhite/Library/Python/2.7/lib/python/site-packages/samtranslator/model/api/api_generator.py", line 212, in _add_cors
    self.definition_body = editor.swagger
  File "/Users/eaddingtonwhite/Library/Python/2.7/lib/python/site-packages/samtranslator/swagger/swagger.py", line 298, in swagger
    return copy.deepcopy(self._doc)
  File "/usr/local/Cellar/python@2/2.7.15_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/copy.py", line 174, in deepcopy
    y = copier(memo)
  File "/usr/local/lib/python2.7/site-packages/cfnlint/decode/node.py", line 75, in __deepcopy__
    result = cls.__new__(cls, self.start_mark, self.end_mark)
AttributeError: 'dict_node' object has no attribute 'start_mark'
```
Here is simple example I made to reproduce
```yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31

Resources:
  Function:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Runtime: nodejs8.10

  Api:
    Type: AWS::Serverless::Api
    Properties:
      Name: test
      StageName: test
      Cors:
        AllowHeaders: "'my_custom_header,content-type'"
        AllowOrigin: "'*'"
        MaxAge: ""
      DefinitionBody:
        swagger: "2.0"
        info:
          version: "1.0"
          title: "test"
        basePath: "/"
        schemes:
          - "https"
        paths:
          /:
            get:
              x-amazon-apigateway-integration:
                uri:
                  Fn::Sub: "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${Function.Arn}/invocations"
                passthroughBehavior: "when_no_match"
                httpMethod: "POST"
                type: "aws_proxy"
```

If you comment out the following lines then issue goes away:
```yaml
      Cors:
        AllowHeaders: "'my_custom_header,content-type'"
        AllowOrigin: "'*'"
        MaxAge: ""
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/cfnlint/decode/node.py`
Content:
```
1 """
2   Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 
4   Permission is hereby granted, free of charge, to any person obtaining a copy of this
5   software and associated documentation files (the "Software"), to deal in the Software
6   without restriction, including without limitation the rights to use, copy, modify,
7   merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
8   permit persons to whom the Software is furnished to do so.
9 
10   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
11   INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
12   PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
13   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
14   OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
15   SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
16 """
17 import sys
18 import logging
19 from copy import deepcopy
20 import six
21 
22 LOGGER = logging.getLogger(__name__)
23 
24 
25 class TemplateAttributeError(AttributeError):
26     """ Custom error to capture Attribute Errors in the Template """
27 
28 
29 def create_str_node_class(cls):
30     """
31     Create string node class
32     """
33     class node_class(cls):
34         """Node class created based on the input class"""
35         def __init__(self, x, start_mark, end_mark):
36             try:
37                 cls.__init__(self, x)
38             except TypeError:
39                 cls.__init__(self)
40             self.start_mark = start_mark
41             self.end_mark = end_mark
42 
43         # pylint: disable=bad-classmethod-argument, unused-argument
44         def __new__(self, x, start_mark, end_mark):
45             if sys.version_info >= (3, 0):
46                 return cls.__new__(self, x)
47 
48             if isinstance(x, six.string_types):
49                 return cls.__new__(self, x.encode('ascii', 'ignore'))
50 
51             return cls.__new__(self, x)
52 
53         def __getattr__(self, name):
54             raise TemplateAttributeError('%s.%s is invalid' % (self.__class__.__name__, name))
55 
56         def __deepcopy__(self, memo):
57             result = str_node(self, self.start_mark, self.end_mark)
58             memo[id(self)] = result
59             return result
60 
61         def __copy__(self):
62             return self
63 
64     node_class.__name__ = '%s_node' % cls.__name__
65     return node_class
66 
67 
68 def create_dict_node_class(cls):
69     """
70     Create dynamic node class
71     """
72     class node_class(cls):
73         """Node class created based on the input class"""
74         def __init__(self, x, start_mark, end_mark):
75             try:
76                 cls.__init__(self, x)
77             except TypeError:
78                 cls.__init__(self)
79             self.start_mark = start_mark
80             self.end_mark = end_mark
81             self.condition_functions = ['Fn::If']
82 
83         def __deepcopy__(self, memo):
84             cls = self.__class__
85             result = cls.__new__(cls, self.start_mark, self.end_mark)
86             memo[id(self)] = result
87             for k, v in self.items():
88                 result[deepcopy(k)] = deepcopy(v, memo)
89 
90             return result
91 
92         def __copy__(self):
93             return self
94 
95         def get_safe(self, key, default=None, path=None, type_t=()):
96             """
97                 Get values in format
98             """
99             path = path or []
100             value = self.get(key, default)
101             if not isinstance(value, (dict)):
102                 if isinstance(value, type_t) or not type_t:
103                     return [(value, (path[:] + [key]))]
104 
105             results = []
106             for sub_v, sub_path in value.items_safe(path):
107                 if isinstance(sub_v, type_t) or not type_t:
108                     results.append((sub_v, sub_path))
109 
110             return results
111 
112         def items_safe(self, path=None, type_t=()):
113             """Get items while handling IFs"""
114             path = path or []
115             if len(self) == 1:
116                 for k, v in self.items():
117                     if k == 'Fn::If':
118                         if isinstance(v, list):
119                             if len(v) == 3:
120                                 for i, if_v in enumerate(v[1:]):
121                                     if isinstance(if_v, dict):
122                                         # yield from if_v.items_safe(path[:] + [k, i - 1])
123                                         # Python 2.7 support
124                                         for items, p in if_v.items_safe(path[:] + [k, i + 1]):
125                                             if isinstance(items, type_t) or not type_t:
126                                                 yield items, p
127                                     elif isinstance(if_v, list):
128                                         if isinstance(if_v, type_t) or not type_t:
129                                             yield if_v, path[:] + [k, i + 1]
130                                     else:
131                                         if isinstance(if_v, type_t) or not type_t:
132                                             yield if_v, path[:] + [k, i + 1]
133                     elif k != 'Ref' and v != 'AWS::NoValue':
134                         if isinstance(self, type_t) or not type_t:
135                             yield self, path[:]
136             else:
137                 if isinstance(self, type_t) or not type_t:
138                     yield self, path[:]
139 
140         def __getattr__(self, name):
141             raise TemplateAttributeError('%s.%s is invalid' % (self.__class__.__name__, name))
142 
143     node_class.__name__ = '%s_node' % cls.__name__
144     return node_class
145 
146 
147 def create_dict_list_class(cls):
148     """
149     Create dynamic list class
150     """
151     class node_class(cls):
152         """Node class created based on the input class"""
153         def __init__(self, x, start_mark, end_mark):
154             try:
155                 cls.__init__(self, x)
156             except TypeError:
157                 cls.__init__(self)
158             self.start_mark = start_mark
159             self.end_mark = end_mark
160             self.condition_functions = ['Fn::If']
161 
162         def __deepcopy__(self, memo):
163             cls = self.__class__
164             result = cls.__new__(cls, self.start_mark, self.end_mark)
165             memo[id(self)] = result
166             for _, v in enumerate(self):
167                 result.append(deepcopy(v, memo))
168 
169             return result
170 
171         def __copy__(self):
172             return self
173 
174         def items_safe(self, path=None, type_t=()):
175             """Get items while handling IFs"""
176             path = path or []
177             for i, v in enumerate(self):
178                 if isinstance(v, dict):
179                     for items, p in v.items_safe(path[:] + [i]):
180                         if isinstance(items, type_t) or not type_t:
181                             yield items, p
182                 else:
183                     if isinstance(v, type_t) or not type_t:
184                         yield v, path[:] + [i]
185 
186         def __getattr__(self, name):
187             raise TemplateAttributeError('%s.%s is invalid' % (self.__class__.__name__, name))
188 
189     node_class.__name__ = '%s_node' % cls.__name__
190     return node_class
191 
192 
193 str_node = create_str_node_class(str)
194 dict_node = create_dict_node_class(dict)
195 list_node = create_dict_list_class(list)
196
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/cfnlint/decode/node.py b/src/cfnlint/decode/node.py
--- a/src/cfnlint/decode/node.py
+++ b/src/cfnlint/decode/node.py
@@ -81,8 +81,7 @@
             self.condition_functions = ['Fn::If']
 
         def __deepcopy__(self, memo):
-            cls = self.__class__
-            result = cls.__new__(cls, self.start_mark, self.end_mark)
+            result = dict_node(self, self.start_mark, self.end_mark)
             memo[id(self)] = result
             for k, v in self.items():
                 result[deepcopy(k)] = deepcopy(v, memo)
@@ -160,8 +159,7 @@
             self.condition_functions = ['Fn::If']
 
         def __deepcopy__(self, memo):
-            cls = self.__class__
-            result = cls.__new__(cls, self.start_mark, self.end_mark)
+            result = list_node([], self.start_mark, self.end_mark)
             memo[id(self)] = result
             for _, v in enumerate(self):
                 result.append(deepcopy(v, memo))

{"golden_diff": "diff --git a/src/cfnlint/decode/node.py b/src/cfnlint/decode/node.py\n--- a/src/cfnlint/decode/node.py\n+++ b/src/cfnlint/decode/node.py\n@@ -81,8 +81,7 @@\n             self.condition_functions = ['Fn::If']\n \n         def __deepcopy__(self, memo):\n-            cls = self.__class__\n-            result = cls.__new__(cls, self.start_mark, self.end_mark)\n+            result = dict_node(self, self.start_mark, self.end_mark)\n             memo[id(self)] = result\n             for k, v in self.items():\n                 result[deepcopy(k)] = deepcopy(v, memo)\n@@ -160,8 +159,7 @@\n             self.condition_functions = ['Fn::If']\n \n         def __deepcopy__(self, memo):\n-            cls = self.__class__\n-            result = cls.__new__(cls, self.start_mark, self.end_mark)\n+            result = list_node([], self.start_mark, self.end_mark)\n             memo[id(self)] = result\n             for _, v in enumerate(self):\n                 result.append(deepcopy(v, memo))\n", "issue": "AWS::Serverless::Api Cors config transform error\n#### cfn-lint version:\r\n``` console\r\n$ cfn-lint --version\r\ncfn-lint 0.8.3\r\n```\r\n\r\n#### Description of issue:\r\nWhen I have a `AWS::Serverless::Api` object with a [Cors Configuration](https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#cors-configuration) object in it I routinely get the following error when linting `template.yaml` \r\n\r\n`E0001 Error transforming template: 'dict_node' object has no attribute 'start_mark'`\r\n\r\nI also got the following stack trace when running \r\n```\r\nTraceback (most recent call last):\r\n  File \"/usr/local/bin/cfn-lint\", line 11, in <module>\r\n    sys.exit(main())\r\n  File \"/usr/local/lib/python2.7/site-packages/cfnlint/__main__.py\", line 36, in main\r\n    args.regions, args.override_spec))\r\n  File \"/usr/local/lib/python2.7/site-packages/cfnlint/core.py\", line 46, in run_cli\r\n    return run_checks(filename, template, rules, regions)\r\n  File \"/usr/local/lib/python2.7/site-packages/cfnlint/core.py\", line 316, in run_checks\r\n    matches.extend(runner.transform())\r\n  File \"/usr/local/lib/python2.7/site-packages/cfnlint/__init__.py\", line 894, in transform\r\n    matches = transform.transform_template()\r\n  File \"/usr/local/lib/python2.7/site-packages/cfnlint/transform.py\", line 115, in transform_template\r\n    sam_translator.translate(sam_template=self._template, parameter_values={}))\r\n  File \"/Users/eaddingtonwhite/Library/Python/2.7/lib/python/site-packages/samtranslator/translator/translator.py\", line 71, in translate\r\n    translated = macro.to_cloudformation(**kwargs)\r\n  File \"/Users/eaddingtonwhite/Library/Python/2.7/lib/python/site-packages/samtranslator/model/sam_resources.py\", line 501, in to_cloudformation\r\n    rest_api, deployment, stage = api_generator.to_cloudformation()\r\n  File \"/Users/eaddingtonwhite/Library/Python/2.7/lib/python/site-packages/samtranslator/model/api/api_generator.py\", line 160, in to_cloudformation\r\n    rest_api = self._construct_rest_api()\r\n  File \"/Users/eaddingtonwhite/Library/Python/2.7/lib/python/site-packages/samtranslator/model/api/api_generator.py\", line 69, in _construct_rest_api\r\n    self._add_cors()\r\n  File \"/Users/eaddingtonwhite/Library/Python/2.7/lib/python/site-packages/samtranslator/model/api/api_generator.py\", line 212, in _add_cors\r\n    self.definition_body = editor.swagger\r\n  File \"/Users/eaddingtonwhite/Library/Python/2.7/lib/python/site-packages/samtranslator/swagger/swagger.py\", line 298, in swagger\r\n    return copy.deepcopy(self._doc)\r\n  File \"/usr/local/Cellar/python@2/2.7.15_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/copy.py\", line 174, in deepcopy\r\n    y = copier(memo)\r\n  File \"/usr/local/lib/python2.7/site-packages/cfnlint/decode/node.py\", line 75, in __deepcopy__\r\n    result = cls.__new__(cls, self.start_mark, self.end_mark)\r\nAttributeError: 'dict_node' object has no attribute 'start_mark'\r\n```\r\nHere is simple example I made to reproduce\r\n```yaml\r\nAWSTemplateFormatVersion: '2010-09-09'\r\nTransform: AWS::Serverless-2016-10-31\r\n\r\nResources:\r\n  Function:\r\n    Type: AWS::Serverless::Function\r\n    Properties:\r\n      CodeUri: hello_world/\r\n      Handler: app.lambda_handler\r\n      Runtime: nodejs8.10\r\n\r\n  Api:\r\n    Type: AWS::Serverless::Api\r\n    Properties:\r\n      Name: test\r\n      StageName: test\r\n      Cors:\r\n        AllowHeaders: \"'my_custom_header,content-type'\"\r\n        AllowOrigin: \"'*'\"\r\n        MaxAge: \"\"\r\n      DefinitionBody:\r\n        swagger: \"2.0\"\r\n        info:\r\n          version: \"1.0\"\r\n          title: \"test\"\r\n        basePath: \"/\"\r\n        schemes:\r\n          - \"https\"\r\n        paths:\r\n          /:\r\n            get:\r\n              x-amazon-apigateway-integration:\r\n                uri:\r\n                  Fn::Sub: \"arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${Function.Arn}/invocations\"\r\n                passthroughBehavior: \"when_no_match\"\r\n                httpMethod: \"POST\"\r\n                type: \"aws_proxy\"\r\n```\r\n\r\nIf you comment out the following lines then issue goes away:\r\n```yaml\r\n      Cors:\r\n        AllowHeaders: \"'my_custom_header,content-type'\"\r\n        AllowOrigin: \"'*'\"\r\n        MaxAge: \"\"\r\n```\n", "before_files": [{"content": "\"\"\"\n  Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n\n  Permission is hereby granted, free of charge, to any person obtaining a copy of this\n  software and associated documentation files (the \"Software\"), to deal in the Software\n  without restriction, including without limitation the rights to use, copy, modify,\n  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n  permit persons to whom the Software is furnished to do so.\n\n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,\n  INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\n  PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\"\"\"\nimport sys\nimport logging\nfrom copy import deepcopy\nimport six\n\nLOGGER = logging.getLogger(__name__)\n\n\nclass TemplateAttributeError(AttributeError):\n    \"\"\" Custom error to capture Attribute Errors in the Template \"\"\"\n\n\ndef create_str_node_class(cls):\n    \"\"\"\n    Create string node class\n    \"\"\"\n    class node_class(cls):\n        \"\"\"Node class created based on the input class\"\"\"\n        def __init__(self, x, start_mark, end_mark):\n            try:\n                cls.__init__(self, x)\n            except TypeError:\n                cls.__init__(self)\n            self.start_mark = start_mark\n            self.end_mark = end_mark\n\n        # pylint: disable=bad-classmethod-argument, unused-argument\n        def __new__(self, x, start_mark, end_mark):\n            if sys.version_info >= (3, 0):\n                return cls.__new__(self, x)\n\n            if isinstance(x, six.string_types):\n                return cls.__new__(self, x.encode('ascii', 'ignore'))\n\n            return cls.__new__(self, x)\n\n        def __getattr__(self, name):\n            raise TemplateAttributeError('%s.%s is invalid' % (self.__class__.__name__, name))\n\n        def __deepcopy__(self, memo):\n            result = str_node(self, self.start_mark, self.end_mark)\n            memo[id(self)] = result\n            return result\n\n        def __copy__(self):\n            return self\n\n    node_class.__name__ = '%s_node' % cls.__name__\n    return node_class\n\n\ndef create_dict_node_class(cls):\n    \"\"\"\n    Create dynamic node class\n    \"\"\"\n    class node_class(cls):\n        \"\"\"Node class created based on the input class\"\"\"\n        def __init__(self, x, start_mark, end_mark):\n            try:\n                cls.__init__(self, x)\n            except TypeError:\n                cls.__init__(self)\n            self.start_mark = start_mark\n            self.end_mark = end_mark\n            self.condition_functions = ['Fn::If']\n\n        def __deepcopy__(self, memo):\n            cls = self.__class__\n            result = cls.__new__(cls, self.start_mark, self.end_mark)\n            memo[id(self)] = result\n            for k, v in self.items():\n                result[deepcopy(k)] = deepcopy(v, memo)\n\n            return result\n\n        def __copy__(self):\n            return self\n\n        def get_safe(self, key, default=None, path=None, type_t=()):\n            \"\"\"\n                Get values in format\n            \"\"\"\n            path = path or []\n            value = self.get(key, default)\n            if not isinstance(value, (dict)):\n                if isinstance(value, type_t) or not type_t:\n                    return [(value, (path[:] + [key]))]\n\n            results = []\n            for sub_v, sub_path in value.items_safe(path):\n                if isinstance(sub_v, type_t) or not type_t:\n                    results.append((sub_v, sub_path))\n\n            return results\n\n        def items_safe(self, path=None, type_t=()):\n            \"\"\"Get items while handling IFs\"\"\"\n            path = path or []\n            if len(self) == 1:\n                for k, v in self.items():\n                    if k == 'Fn::If':\n                        if isinstance(v, list):\n                            if len(v) == 3:\n                                for i, if_v in enumerate(v[1:]):\n                                    if isinstance(if_v, dict):\n                                        # yield from if_v.items_safe(path[:] + [k, i - 1])\n                                        # Python 2.7 support\n                                        for items, p in if_v.items_safe(path[:] + [k, i + 1]):\n                                            if isinstance(items, type_t) or not type_t:\n                                                yield items, p\n                                    elif isinstance(if_v, list):\n                                        if isinstance(if_v, type_t) or not type_t:\n                                            yield if_v, path[:] + [k, i + 1]\n                                    else:\n                                        if isinstance(if_v, type_t) or not type_t:\n                                            yield if_v, path[:] + [k, i + 1]\n                    elif k != 'Ref' and v != 'AWS::NoValue':\n                        if isinstance(self, type_t) or not type_t:\n                            yield self, path[:]\n            else:\n                if isinstance(self, type_t) or not type_t:\n                    yield self, path[:]\n\n        def __getattr__(self, name):\n            raise TemplateAttributeError('%s.%s is invalid' % (self.__class__.__name__, name))\n\n    node_class.__name__ = '%s_node' % cls.__name__\n    return node_class\n\n\ndef create_dict_list_class(cls):\n    \"\"\"\n    Create dynamic list class\n    \"\"\"\n    class node_class(cls):\n        \"\"\"Node class created based on the input class\"\"\"\n        def __init__(self, x, start_mark, end_mark):\n            try:\n                cls.__init__(self, x)\n            except TypeError:\n                cls.__init__(self)\n            self.start_mark = start_mark\n            self.end_mark = end_mark\n            self.condition_functions = ['Fn::If']\n\n        def __deepcopy__(self, memo):\n            cls = self.__class__\n            result = cls.__new__(cls, self.start_mark, self.end_mark)\n            memo[id(self)] = result\n            for _, v in enumerate(self):\n                result.append(deepcopy(v, memo))\n\n            return result\n\n        def __copy__(self):\n            return self\n\n        def items_safe(self, path=None, type_t=()):\n            \"\"\"Get items while handling IFs\"\"\"\n            path = path or []\n            for i, v in enumerate(self):\n                if isinstance(v, dict):\n                    for items, p in v.items_safe(path[:] + [i]):\n                        if isinstance(items, type_t) or not type_t:\n                            yield items, p\n                else:\n                    if isinstance(v, type_t) or not type_t:\n                        yield v, path[:] + [i]\n\n        def __getattr__(self, name):\n            raise TemplateAttributeError('%s.%s is invalid' % (self.__class__.__name__, name))\n\n    node_class.__name__ = '%s_node' % cls.__name__\n    return node_class\n\n\nstr_node = create_str_node_class(str)\ndict_node = create_dict_node_class(dict)\nlist_node = create_dict_list_class(list)\n", "path": "src/cfnlint/decode/node.py"}], "after_files": [{"content": "\"\"\"\n  Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n\n  Permission is hereby granted, free of charge, to any person obtaining a copy of this\n  software and associated documentation files (the \"Software\"), to deal in the Software\n  without restriction, including without limitation the rights to use, copy, modify,\n  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n  permit persons to whom the Software is furnished to do so.\n\n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,\n  INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\n  PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\"\"\"\nimport sys\nimport logging\nfrom copy import deepcopy\nimport six\n\nLOGGER = logging.getLogger(__name__)\n\n\nclass TemplateAttributeError(AttributeError):\n    \"\"\" Custom error to capture Attribute Errors in the Template \"\"\"\n\n\ndef create_str_node_class(cls):\n    \"\"\"\n    Create string node class\n    \"\"\"\n    class node_class(cls):\n        \"\"\"Node class created based on the input class\"\"\"\n        def __init__(self, x, start_mark, end_mark):\n            try:\n                cls.__init__(self, x)\n            except TypeError:\n                cls.__init__(self)\n            self.start_mark = start_mark\n            self.end_mark = end_mark\n\n        # pylint: disable=bad-classmethod-argument, unused-argument\n        def __new__(self, x, start_mark, end_mark):\n            if sys.version_info >= (3, 0):\n                return cls.__new__(self, x)\n\n            if isinstance(x, six.string_types):\n                return cls.__new__(self, x.encode('ascii', 'ignore'))\n\n            return cls.__new__(self, x)\n\n        def __getattr__(self, name):\n            raise TemplateAttributeError('%s.%s is invalid' % (self.__class__.__name__, name))\n\n        def __deepcopy__(self, memo):\n            result = str_node(self, self.start_mark, self.end_mark)\n            memo[id(self)] = result\n            return result\n\n        def __copy__(self):\n            return self\n\n    node_class.__name__ = '%s_node' % cls.__name__\n    return node_class\n\n\ndef create_dict_node_class(cls):\n    \"\"\"\n    Create dynamic node class\n    \"\"\"\n    class node_class(cls):\n        \"\"\"Node class created based on the input class\"\"\"\n        def __init__(self, x, start_mark, end_mark):\n            try:\n                cls.__init__(self, x)\n            except TypeError:\n                cls.__init__(self)\n            self.start_mark = start_mark\n            self.end_mark = end_mark\n            self.condition_functions = ['Fn::If']\n\n        def __deepcopy__(self, memo):\n            result = dict_node(self, self.start_mark, self.end_mark)\n            memo[id(self)] = result\n            for k, v in self.items():\n                result[deepcopy(k)] = deepcopy(v, memo)\n\n            return result\n\n        def __copy__(self):\n            return self\n\n        def get_safe(self, key, default=None, path=None, type_t=()):\n            \"\"\"\n                Get values in format\n            \"\"\"\n            path = path or []\n            value = self.get(key, default)\n            if not isinstance(value, (dict)):\n                if isinstance(value, type_t) or not type_t:\n                    return [(value, (path[:] + [key]))]\n\n            results = []\n            for sub_v, sub_path in value.items_safe(path):\n                if isinstance(sub_v, type_t) or not type_t:\n                    results.append((sub_v, sub_path))\n\n            return results\n\n        def items_safe(self, path=None, type_t=()):\n            \"\"\"Get items while handling IFs\"\"\"\n            path = path or []\n            if len(self) == 1:\n                for k, v in self.items():\n                    if k == 'Fn::If':\n                        if isinstance(v, list):\n                            if len(v) == 3:\n                                for i, if_v in enumerate(v[1:]):\n                                    if isinstance(if_v, dict):\n                                        # yield from if_v.items_safe(path[:] + [k, i - 1])\n                                        # Python 2.7 support\n                                        for items, p in if_v.items_safe(path[:] + [k, i + 1]):\n                                            if isinstance(items, type_t) or not type_t:\n                                                yield items, p\n                                    elif isinstance(if_v, list):\n                                        if isinstance(if_v, type_t) or not type_t:\n                                            yield if_v, path[:] + [k, i + 1]\n                                    else:\n                                        if isinstance(if_v, type_t) or not type_t:\n                                            yield if_v, path[:] + [k, i + 1]\n                    elif k != 'Ref' and v != 'AWS::NoValue':\n                        if isinstance(self, type_t) or not type_t:\n                            yield self, path[:]\n            else:\n                if isinstance(self, type_t) or not type_t:\n                    yield self, path[:]\n\n        def __getattr__(self, name):\n            raise TemplateAttributeError('%s.%s is invalid' % (self.__class__.__name__, name))\n\n    node_class.__name__ = '%s_node' % cls.__name__\n    return node_class\n\n\ndef create_dict_list_class(cls):\n    \"\"\"\n    Create dynamic list class\n    \"\"\"\n    class node_class(cls):\n        \"\"\"Node class created based on the input class\"\"\"\n        def __init__(self, x, start_mark, end_mark):\n            try:\n                cls.__init__(self, x)\n            except TypeError:\n                cls.__init__(self)\n            self.start_mark = start_mark\n            self.end_mark = end_mark\n            self.condition_functions = ['Fn::If']\n\n        def __deepcopy__(self, memo):\n            result = list_node([], self.start_mark, self.end_mark)\n            memo[id(self)] = result\n            for _, v in enumerate(self):\n                result.append(deepcopy(v, memo))\n\n            return result\n\n        def __copy__(self):\n            return self\n\n        def items_safe(self, path=None, type_t=()):\n            \"\"\"Get items while handling IFs\"\"\"\n            path = path or []\n            for i, v in enumerate(self):\n                if isinstance(v, dict):\n                    for items, p in v.items_safe(path[:] + [i]):\n                        if isinstance(items, type_t) or not type_t:\n                            yield items, p\n                else:\n                    if isinstance(v, type_t) or not type_t:\n                        yield v, path[:] + [i]\n\n        def __getattr__(self, name):\n            raise TemplateAttributeError('%s.%s is invalid' % (self.__class__.__name__, name))\n\n    node_class.__name__ = '%s_node' % cls.__name__\n    return node_class\n\n\nstr_node = create_str_node_class(str)\ndict_node = create_dict_node_class(dict)\nlist_node = create_dict_list_class(list)\n", "path": "src/cfnlint/decode/node.py"}]}