We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
E3002, E3003, E3012 - AWS::SSM::MaintenanceWindowTarget errors
cfn-lint version: 0.19.1

cfn-lint -u has been run

I am unable to to get a clean lint on a SSM template file that seems alright and that has loaded properly in AWS.  Would really appreciate any assistance. 

The documentation is here on MaintenanceWindowTarget:
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ssm-maintenancewindowtarget.html

And the associated targets:
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ssm-maintenancewindowtarget-targets.html

The below cf should be syntactically correct..... 

```
  BaselinePatchDailySSMMaintenanceWindowTarget:
    Type: AWS::SSM::MaintenanceWindowTarget
    Properties:
      Name: BaselinePatchDailyTarget
      Description: Systems with Tag Key=Patch,Value=Daily.
      WindowId: !Ref BaselinePatchDailySSMMaintenanceWindow
      ResourceType: INSTANCE
      Targets:
      - Key: tag:Patch
        Values:
        - Daily
        - daily
```
Results in the following cfn-lint errors:

```
E0002 Unknown exception while processing rule E3002: 'AWS::SSM::MaintenanceWindowTarget.Target'
BaselineSSMConfig.yaml:1:1

E0002 Unknown exception while processing rule E3003: 'AWS::SSM::MaintenanceWindowTarget.Target'
BaselineSSMConfig.yaml:1:1

E3012 Property Resources/BaselinePatchDailySSMMaintenanceWindowTarget/Properties/Targets/0 should be of type String
BaselineSSMConfig.yaml:292:9
```
Edited file as follows to attempt to make target a string:

```
  BaselinePatchDailySSMMaintenanceWindowTarget:
    Type: AWS::SSM::MaintenanceWindowTarget
    Properties:
      Name: BaselinePatchDailyTarget
      Description: Systems with Tag Key=Patch,Value=Daily.
      WindowId: !Ref BaselinePatchDailySSMMaintenanceWindow
      ResourceType: INSTANCE
      Targets: Key=tag:Patch,Values=Daily,daily
```
Results in the following cfn-lint error:

```
E3002 Property Targets should be of type List for resource BaselinePatchDailySSMMaintenanceWindowTarget
BaselineSSMConfig.yaml:291:7
```
Attempting to make the string a list:
```
  BaselinePatchDailySSMMaintenanceWindowTarget:
    Type: AWS::SSM::MaintenanceWindowTarget
    Properties:
      Name: BaselinePatchDailyTarget
      Description: Systems with Tag Key=Patch,Value=Daily.
      WindowId: !Ref BaselinePatchDailySSMMaintenanceWindow
      ResourceType: INSTANCE
      Targets:
      - Key=tag:Patch,Values=Daily,daily
```
Results in the following errors:
```
E0002 Unknown exception while processing rule E3002: 'AWS::SSM::MaintenanceWindowTarget.Target'
BaselineSSMConfig.yaml:1:1

E0002 Unknown exception while processing rule E3003: 'AWS::SSM::MaintenanceWindowTarget.Target'
BaselineSSMConfig.yaml:1:1
```

Thanks!



--- 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/rules/resources/properties/ValuePrimitiveType.py`
Content:
```
1 """
2   Copyright 2019 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 six
19 from cfnlint import CloudFormationLintRule
20 from cfnlint import RuleMatch
21 import cfnlint.helpers
22 
23 
24 class ValuePrimitiveType(CloudFormationLintRule):
25     """Check if Resource PrimitiveTypes are correct"""
26     id = 'E3012'
27     shortdesc = 'Check resource properties values'
28     description = 'Checks resource property values with Primitive Types for ' \
29                   'values that match those types.'
30     source_url = 'https://github.com/aws-cloudformation/cfn-python-lint/blob/master/docs/cfn-resource-specification.md#valueprimitivetype'
31     tags = ['resources']
32 
33     def __init__(self):
34         """Init"""
35         super(ValuePrimitiveType, self).__init__()
36         self.resource_specs = []
37         self.property_specs = []
38         self.config_definition = {
39             'strict': {
40                 'default': True,
41                 'type': 'boolean'
42             }
43         }
44         self.configure()
45 
46     def initialize(self, cfn):
47         """Initialize the rule"""
48         specs = cfnlint.helpers.RESOURCE_SPECS.get(cfn.regions[0])
49         self.property_specs = specs.get('PropertyTypes')
50         self.resource_specs = specs.get('ResourceTypes')
51         for resource_spec in self.resource_specs:
52             self.resource_property_types.append(resource_spec)
53         for property_spec in self.property_specs:
54             self.resource_sub_property_types.append(property_spec)
55 
56     def _value_check(self, value, path, item_type, extra_args):
57         """ Checks non strict """
58         matches = []
59         if not self.config['strict']:
60             try:
61                 if item_type in ['String']:
62                     str(value)
63                 elif item_type in ['Boolean']:
64                     if value not in ['True', 'true', 'False', 'false']:
65                         message = 'Property %s should be of type %s' % ('/'.join(map(str, path)), item_type)
66                         matches.append(RuleMatch(path, message, **extra_args))
67                 elif item_type in ['Integer', 'Long', 'Double']:
68                     if isinstance(value, bool):
69                         message = 'Property %s should be of type %s' % ('/'.join(map(str, path)), item_type)
70                         matches.append(RuleMatch(path, message, **extra_args))
71                     elif item_type in ['Integer']:
72                         int(value)
73                     elif item_type in ['Long']:
74                         # Some times python will strip the decimals when doing a conversion
75                         if isinstance(value, float):
76                             message = 'Property %s should be of type %s' % ('/'.join(map(str, path)), item_type)
77                             matches.append(RuleMatch(path, message, **extra_args))
78                         if sys.version_info < (3,):
79                             long(value)  # pylint: disable=undefined-variable
80                         else:
81                             int(value)
82                     else:  # has to be a Double
83                         float(value)
84             except Exception:  # pylint: disable=W0703
85                 message = 'Property %s should be of type %s' % ('/'.join(map(str, path)), item_type)
86                 matches.append(RuleMatch(path, message, **extra_args))
87         else:
88             message = 'Property %s should be of type %s' % ('/'.join(map(str, path)), item_type)
89             matches.append(RuleMatch(path, message, **extra_args))
90 
91         return matches
92 
93     def check_primitive_type(self, value, item_type, path):
94         """Chec item type"""
95         matches = []
96 
97         if isinstance(value, dict) and item_type == 'Json':
98             return matches
99         if item_type in ['String']:
100             if not isinstance(value, (six.string_types)):
101                 extra_args = {'actual_type': type(value).__name__, 'expected_type': str.__name__}
102                 matches.extend(self._value_check(value, path, item_type, extra_args))
103         elif item_type in ['Boolean']:
104             if not isinstance(value, (bool)):
105                 extra_args = {'actual_type': type(value).__name__, 'expected_type': bool.__name__}
106                 matches.extend(self._value_check(value, path, item_type, extra_args))
107         elif item_type in ['Double']:
108             if not isinstance(value, (float, int)):
109                 extra_args = {'actual_type': type(value).__name__, 'expected_type': [float.__name__, int.__name__]}
110                 matches.extend(self._value_check(value, path, item_type, extra_args))
111         elif item_type in ['Integer']:
112             if not isinstance(value, (int)):
113                 extra_args = {'actual_type': type(value).__name__, 'expected_type': int.__name__}
114                 matches.extend(self._value_check(value, path, item_type, extra_args))
115         elif item_type in ['Long']:
116             if sys.version_info < (3,):
117                 integer_types = (int, long,)  # pylint: disable=undefined-variable
118             else:
119                 integer_types = (int,)
120             if not isinstance(value, integer_types):
121                 extra_args = {'actual_type': type(value).__name__, 'expected_type': ' or '.join([x.__name__ for x in integer_types])}
122                 matches.extend(self._value_check(value, path, item_type, extra_args))
123         elif isinstance(value, list):
124             message = 'Property should be of type %s at %s' % (item_type, '/'.join(map(str, path)))
125             extra_args = {'actual_type': type(value).__name__, 'expected_type': list.__name__}
126             matches.append(RuleMatch(path, message, **extra_args))
127 
128         return matches
129 
130     def check_value(self, value, path, **kwargs):
131         """Check Value"""
132         matches = []
133         primitive_type = kwargs.get('primitive_type', {})
134         item_type = kwargs.get('item_type', {})
135         if item_type in ['Map']:
136             if isinstance(value, dict):
137                 for map_key, map_value in value.items():
138                     if not isinstance(map_value, dict):
139                         matches.extend(self.check_primitive_type(map_value, primitive_type, path + [map_key]))
140         else:
141             matches.extend(self.check_primitive_type(value, primitive_type, path))
142 
143         return matches
144 
145     def check(self, cfn, properties, specs, path):
146         """Check itself"""
147         matches = []
148 
149         for prop in properties:
150             if prop in specs:
151                 primitive_type = specs.get(prop).get('PrimitiveType')
152                 if not primitive_type:
153                     primitive_type = specs.get(prop).get('PrimitiveItemType')
154                 if specs.get(prop).get('Type') in ['List', 'Map']:
155                     item_type = specs.get(prop).get('Type')
156                 else:
157                     item_type = None
158                 if primitive_type:
159                     matches.extend(
160                         cfn.check_value(
161                             properties, prop, path,
162                             check_value=self.check_value,
163                             primitive_type=primitive_type,
164                             item_type=item_type
165                         )
166                     )
167 
168         return matches
169 
170     def match_resource_sub_properties(self, properties, property_type, path, cfn):
171         """Match for sub properties"""
172         matches = []
173 
174         if self.property_specs.get(property_type, {}).get('Properties'):
175             property_specs = self.property_specs.get(property_type, {}).get('Properties', {})
176             matches.extend(self.check(cfn, properties, property_specs, path))
177 
178         return matches
179 
180     def match_resource_properties(self, properties, resource_type, path, cfn):
181         """Check CloudFormation Properties"""
182         matches = []
183         resource_specs = self.resource_specs.get(resource_type, {}).get('Properties', {})
184         matches.extend(self.check(cfn, properties, resource_specs, path))
185 
186         return matches
187
```
--- 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/rules/resources/properties/ValuePrimitiveType.py b/src/cfnlint/rules/resources/properties/ValuePrimitiveType.py
--- a/src/cfnlint/rules/resources/properties/ValuePrimitiveType.py
+++ b/src/cfnlint/rules/resources/properties/ValuePrimitiveType.py
@@ -138,6 +138,10 @@
                     if not isinstance(map_value, dict):
                         matches.extend(self.check_primitive_type(map_value, primitive_type, path + [map_key]))
         else:
+            # some properties support primitive types and objects
+            # skip in the case it could be an object and the value is a object
+            if item_type and isinstance(value, dict):
+                return matches
             matches.extend(self.check_primitive_type(value, primitive_type, path))
 
         return matches

{"golden_diff": "diff --git a/src/cfnlint/rules/resources/properties/ValuePrimitiveType.py b/src/cfnlint/rules/resources/properties/ValuePrimitiveType.py\n--- a/src/cfnlint/rules/resources/properties/ValuePrimitiveType.py\n+++ b/src/cfnlint/rules/resources/properties/ValuePrimitiveType.py\n@@ -138,6 +138,10 @@\n                     if not isinstance(map_value, dict):\n                         matches.extend(self.check_primitive_type(map_value, primitive_type, path + [map_key]))\n         else:\n+            # some properties support primitive types and objects\n+            # skip in the case it could be an object and the value is a object\n+            if item_type and isinstance(value, dict):\n+                return matches\n             matches.extend(self.check_primitive_type(value, primitive_type, path))\n \n         return matches\n", "issue": "E3002, E3003, E3012 - AWS::SSM::MaintenanceWindowTarget errors\ncfn-lint version: 0.19.1\r\n\r\ncfn-lint -u has been run\r\n\r\nI am unable to to get a clean lint on a SSM template file that seems alright and that has loaded properly in AWS.  Would really appreciate any assistance. \r\n\r\nThe documentation is here on MaintenanceWindowTarget:\r\nhttps://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ssm-maintenancewindowtarget.html\r\n\r\nAnd the associated targets:\r\nhttps://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ssm-maintenancewindowtarget-targets.html\r\n\r\nThe below cf should be syntactically correct..... \r\n\r\n```\r\n  BaselinePatchDailySSMMaintenanceWindowTarget:\r\n    Type: AWS::SSM::MaintenanceWindowTarget\r\n    Properties:\r\n      Name: BaselinePatchDailyTarget\r\n      Description: Systems with Tag Key=Patch,Value=Daily.\r\n      WindowId: !Ref BaselinePatchDailySSMMaintenanceWindow\r\n      ResourceType: INSTANCE\r\n      Targets:\r\n      - Key: tag:Patch\r\n        Values:\r\n        - Daily\r\n        - daily\r\n```\r\nResults in the following cfn-lint errors:\r\n\r\n```\r\nE0002 Unknown exception while processing rule E3002: 'AWS::SSM::MaintenanceWindowTarget.Target'\r\nBaselineSSMConfig.yaml:1:1\r\n\r\nE0002 Unknown exception while processing rule E3003: 'AWS::SSM::MaintenanceWindowTarget.Target'\r\nBaselineSSMConfig.yaml:1:1\r\n\r\nE3012 Property Resources/BaselinePatchDailySSMMaintenanceWindowTarget/Properties/Targets/0 should be of type String\r\nBaselineSSMConfig.yaml:292:9\r\n```\r\nEdited file as follows to attempt to make target a string:\r\n\r\n```\r\n  BaselinePatchDailySSMMaintenanceWindowTarget:\r\n    Type: AWS::SSM::MaintenanceWindowTarget\r\n    Properties:\r\n      Name: BaselinePatchDailyTarget\r\n      Description: Systems with Tag Key=Patch,Value=Daily.\r\n      WindowId: !Ref BaselinePatchDailySSMMaintenanceWindow\r\n      ResourceType: INSTANCE\r\n      Targets: Key=tag:Patch,Values=Daily,daily\r\n```\r\nResults in the following cfn-lint error:\r\n\r\n```\r\nE3002 Property Targets should be of type List for resource BaselinePatchDailySSMMaintenanceWindowTarget\r\nBaselineSSMConfig.yaml:291:7\r\n```\r\nAttempting to make the string a list:\r\n```\r\n  BaselinePatchDailySSMMaintenanceWindowTarget:\r\n    Type: AWS::SSM::MaintenanceWindowTarget\r\n    Properties:\r\n      Name: BaselinePatchDailyTarget\r\n      Description: Systems with Tag Key=Patch,Value=Daily.\r\n      WindowId: !Ref BaselinePatchDailySSMMaintenanceWindow\r\n      ResourceType: INSTANCE\r\n      Targets:\r\n      - Key=tag:Patch,Values=Daily,daily\r\n```\r\nResults in the following errors:\r\n```\r\nE0002 Unknown exception while processing rule E3002: 'AWS::SSM::MaintenanceWindowTarget.Target'\r\nBaselineSSMConfig.yaml:1:1\r\n\r\nE0002 Unknown exception while processing rule E3003: 'AWS::SSM::MaintenanceWindowTarget.Target'\r\nBaselineSSMConfig.yaml:1:1\r\n```\r\n\r\nThanks!\r\n\r\n\n", "before_files": [{"content": "\"\"\"\n  Copyright 2019 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 six\nfrom cfnlint import CloudFormationLintRule\nfrom cfnlint import RuleMatch\nimport cfnlint.helpers\n\n\nclass ValuePrimitiveType(CloudFormationLintRule):\n    \"\"\"Check if Resource PrimitiveTypes are correct\"\"\"\n    id = 'E3012'\n    shortdesc = 'Check resource properties values'\n    description = 'Checks resource property values with Primitive Types for ' \\\n                  'values that match those types.'\n    source_url = 'https://github.com/aws-cloudformation/cfn-python-lint/blob/master/docs/cfn-resource-specification.md#valueprimitivetype'\n    tags = ['resources']\n\n    def __init__(self):\n        \"\"\"Init\"\"\"\n        super(ValuePrimitiveType, self).__init__()\n        self.resource_specs = []\n        self.property_specs = []\n        self.config_definition = {\n            'strict': {\n                'default': True,\n                'type': 'boolean'\n            }\n        }\n        self.configure()\n\n    def initialize(self, cfn):\n        \"\"\"Initialize the rule\"\"\"\n        specs = cfnlint.helpers.RESOURCE_SPECS.get(cfn.regions[0])\n        self.property_specs = specs.get('PropertyTypes')\n        self.resource_specs = specs.get('ResourceTypes')\n        for resource_spec in self.resource_specs:\n            self.resource_property_types.append(resource_spec)\n        for property_spec in self.property_specs:\n            self.resource_sub_property_types.append(property_spec)\n\n    def _value_check(self, value, path, item_type, extra_args):\n        \"\"\" Checks non strict \"\"\"\n        matches = []\n        if not self.config['strict']:\n            try:\n                if item_type in ['String']:\n                    str(value)\n                elif item_type in ['Boolean']:\n                    if value not in ['True', 'true', 'False', 'false']:\n                        message = 'Property %s should be of type %s' % ('/'.join(map(str, path)), item_type)\n                        matches.append(RuleMatch(path, message, **extra_args))\n                elif item_type in ['Integer', 'Long', 'Double']:\n                    if isinstance(value, bool):\n                        message = 'Property %s should be of type %s' % ('/'.join(map(str, path)), item_type)\n                        matches.append(RuleMatch(path, message, **extra_args))\n                    elif item_type in ['Integer']:\n                        int(value)\n                    elif item_type in ['Long']:\n                        # Some times python will strip the decimals when doing a conversion\n                        if isinstance(value, float):\n                            message = 'Property %s should be of type %s' % ('/'.join(map(str, path)), item_type)\n                            matches.append(RuleMatch(path, message, **extra_args))\n                        if sys.version_info < (3,):\n                            long(value)  # pylint: disable=undefined-variable\n                        else:\n                            int(value)\n                    else:  # has to be a Double\n                        float(value)\n            except Exception:  # pylint: disable=W0703\n                message = 'Property %s should be of type %s' % ('/'.join(map(str, path)), item_type)\n                matches.append(RuleMatch(path, message, **extra_args))\n        else:\n            message = 'Property %s should be of type %s' % ('/'.join(map(str, path)), item_type)\n            matches.append(RuleMatch(path, message, **extra_args))\n\n        return matches\n\n    def check_primitive_type(self, value, item_type, path):\n        \"\"\"Chec item type\"\"\"\n        matches = []\n\n        if isinstance(value, dict) and item_type == 'Json':\n            return matches\n        if item_type in ['String']:\n            if not isinstance(value, (six.string_types)):\n                extra_args = {'actual_type': type(value).__name__, 'expected_type': str.__name__}\n                matches.extend(self._value_check(value, path, item_type, extra_args))\n        elif item_type in ['Boolean']:\n            if not isinstance(value, (bool)):\n                extra_args = {'actual_type': type(value).__name__, 'expected_type': bool.__name__}\n                matches.extend(self._value_check(value, path, item_type, extra_args))\n        elif item_type in ['Double']:\n            if not isinstance(value, (float, int)):\n                extra_args = {'actual_type': type(value).__name__, 'expected_type': [float.__name__, int.__name__]}\n                matches.extend(self._value_check(value, path, item_type, extra_args))\n        elif item_type in ['Integer']:\n            if not isinstance(value, (int)):\n                extra_args = {'actual_type': type(value).__name__, 'expected_type': int.__name__}\n                matches.extend(self._value_check(value, path, item_type, extra_args))\n        elif item_type in ['Long']:\n            if sys.version_info < (3,):\n                integer_types = (int, long,)  # pylint: disable=undefined-variable\n            else:\n                integer_types = (int,)\n            if not isinstance(value, integer_types):\n                extra_args = {'actual_type': type(value).__name__, 'expected_type': ' or '.join([x.__name__ for x in integer_types])}\n                matches.extend(self._value_check(value, path, item_type, extra_args))\n        elif isinstance(value, list):\n            message = 'Property should be of type %s at %s' % (item_type, '/'.join(map(str, path)))\n            extra_args = {'actual_type': type(value).__name__, 'expected_type': list.__name__}\n            matches.append(RuleMatch(path, message, **extra_args))\n\n        return matches\n\n    def check_value(self, value, path, **kwargs):\n        \"\"\"Check Value\"\"\"\n        matches = []\n        primitive_type = kwargs.get('primitive_type', {})\n        item_type = kwargs.get('item_type', {})\n        if item_type in ['Map']:\n            if isinstance(value, dict):\n                for map_key, map_value in value.items():\n                    if not isinstance(map_value, dict):\n                        matches.extend(self.check_primitive_type(map_value, primitive_type, path + [map_key]))\n        else:\n            matches.extend(self.check_primitive_type(value, primitive_type, path))\n\n        return matches\n\n    def check(self, cfn, properties, specs, path):\n        \"\"\"Check itself\"\"\"\n        matches = []\n\n        for prop in properties:\n            if prop in specs:\n                primitive_type = specs.get(prop).get('PrimitiveType')\n                if not primitive_type:\n                    primitive_type = specs.get(prop).get('PrimitiveItemType')\n                if specs.get(prop).get('Type') in ['List', 'Map']:\n                    item_type = specs.get(prop).get('Type')\n                else:\n                    item_type = None\n                if primitive_type:\n                    matches.extend(\n                        cfn.check_value(\n                            properties, prop, path,\n                            check_value=self.check_value,\n                            primitive_type=primitive_type,\n                            item_type=item_type\n                        )\n                    )\n\n        return matches\n\n    def match_resource_sub_properties(self, properties, property_type, path, cfn):\n        \"\"\"Match for sub properties\"\"\"\n        matches = []\n\n        if self.property_specs.get(property_type, {}).get('Properties'):\n            property_specs = self.property_specs.get(property_type, {}).get('Properties', {})\n            matches.extend(self.check(cfn, properties, property_specs, path))\n\n        return matches\n\n    def match_resource_properties(self, properties, resource_type, path, cfn):\n        \"\"\"Check CloudFormation Properties\"\"\"\n        matches = []\n        resource_specs = self.resource_specs.get(resource_type, {}).get('Properties', {})\n        matches.extend(self.check(cfn, properties, resource_specs, path))\n\n        return matches\n", "path": "src/cfnlint/rules/resources/properties/ValuePrimitiveType.py"}], "after_files": [{"content": "\"\"\"\n  Copyright 2019 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 six\nfrom cfnlint import CloudFormationLintRule\nfrom cfnlint import RuleMatch\nimport cfnlint.helpers\n\n\nclass ValuePrimitiveType(CloudFormationLintRule):\n    \"\"\"Check if Resource PrimitiveTypes are correct\"\"\"\n    id = 'E3012'\n    shortdesc = 'Check resource properties values'\n    description = 'Checks resource property values with Primitive Types for ' \\\n                  'values that match those types.'\n    source_url = 'https://github.com/aws-cloudformation/cfn-python-lint/blob/master/docs/cfn-resource-specification.md#valueprimitivetype'\n    tags = ['resources']\n\n    def __init__(self):\n        \"\"\"Init\"\"\"\n        super(ValuePrimitiveType, self).__init__()\n        self.resource_specs = []\n        self.property_specs = []\n        self.config_definition = {\n            'strict': {\n                'default': True,\n                'type': 'boolean'\n            }\n        }\n        self.configure()\n\n    def initialize(self, cfn):\n        \"\"\"Initialize the rule\"\"\"\n        specs = cfnlint.helpers.RESOURCE_SPECS.get(cfn.regions[0])\n        self.property_specs = specs.get('PropertyTypes')\n        self.resource_specs = specs.get('ResourceTypes')\n        for resource_spec in self.resource_specs:\n            self.resource_property_types.append(resource_spec)\n        for property_spec in self.property_specs:\n            self.resource_sub_property_types.append(property_spec)\n\n    def _value_check(self, value, path, item_type, extra_args):\n        \"\"\" Checks non strict \"\"\"\n        matches = []\n        if not self.config['strict']:\n            try:\n                if item_type in ['String']:\n                    str(value)\n                elif item_type in ['Boolean']:\n                    if value not in ['True', 'true', 'False', 'false']:\n                        message = 'Property %s should be of type %s' % ('/'.join(map(str, path)), item_type)\n                        matches.append(RuleMatch(path, message, **extra_args))\n                elif item_type in ['Integer', 'Long', 'Double']:\n                    if isinstance(value, bool):\n                        message = 'Property %s should be of type %s' % ('/'.join(map(str, path)), item_type)\n                        matches.append(RuleMatch(path, message, **extra_args))\n                    elif item_type in ['Integer']:\n                        int(value)\n                    elif item_type in ['Long']:\n                        # Some times python will strip the decimals when doing a conversion\n                        if isinstance(value, float):\n                            message = 'Property %s should be of type %s' % ('/'.join(map(str, path)), item_type)\n                            matches.append(RuleMatch(path, message, **extra_args))\n                        if sys.version_info < (3,):\n                            long(value)  # pylint: disable=undefined-variable\n                        else:\n                            int(value)\n                    else:  # has to be a Double\n                        float(value)\n            except Exception:  # pylint: disable=W0703\n                message = 'Property %s should be of type %s' % ('/'.join(map(str, path)), item_type)\n                matches.append(RuleMatch(path, message, **extra_args))\n        else:\n            message = 'Property %s should be of type %s' % ('/'.join(map(str, path)), item_type)\n            matches.append(RuleMatch(path, message, **extra_args))\n\n        return matches\n\n    def check_primitive_type(self, value, item_type, path):\n        \"\"\"Chec item type\"\"\"\n        matches = []\n\n        if isinstance(value, dict) and item_type == 'Json':\n            return matches\n        if item_type in ['String']:\n            if not isinstance(value, (six.string_types)):\n                extra_args = {'actual_type': type(value).__name__, 'expected_type': str.__name__}\n                matches.extend(self._value_check(value, path, item_type, extra_args))\n        elif item_type in ['Boolean']:\n            if not isinstance(value, (bool)):\n                extra_args = {'actual_type': type(value).__name__, 'expected_type': bool.__name__}\n                matches.extend(self._value_check(value, path, item_type, extra_args))\n        elif item_type in ['Double']:\n            if not isinstance(value, (float, int)):\n                extra_args = {'actual_type': type(value).__name__, 'expected_type': [float.__name__, int.__name__]}\n                matches.extend(self._value_check(value, path, item_type, extra_args))\n        elif item_type in ['Integer']:\n            if not isinstance(value, (int)):\n                extra_args = {'actual_type': type(value).__name__, 'expected_type': int.__name__}\n                matches.extend(self._value_check(value, path, item_type, extra_args))\n        elif item_type in ['Long']:\n            if sys.version_info < (3,):\n                integer_types = (int, long,)  # pylint: disable=undefined-variable\n            else:\n                integer_types = (int,)\n            if not isinstance(value, integer_types):\n                extra_args = {'actual_type': type(value).__name__, 'expected_type': ' or '.join([x.__name__ for x in integer_types])}\n                matches.extend(self._value_check(value, path, item_type, extra_args))\n        elif isinstance(value, list):\n            message = 'Property should be of type %s at %s' % (item_type, '/'.join(map(str, path)))\n            extra_args = {'actual_type': type(value).__name__, 'expected_type': list.__name__}\n            matches.append(RuleMatch(path, message, **extra_args))\n\n        return matches\n\n    def check_value(self, value, path, **kwargs):\n        \"\"\"Check Value\"\"\"\n        matches = []\n        primitive_type = kwargs.get('primitive_type', {})\n        item_type = kwargs.get('item_type', {})\n        if item_type in ['Map']:\n            if isinstance(value, dict):\n                for map_key, map_value in value.items():\n                    if not isinstance(map_value, dict):\n                        matches.extend(self.check_primitive_type(map_value, primitive_type, path + [map_key]))\n        else:\n            # some properties support primitive types and objects\n            # skip in the case it could be an object and the value is a object\n            if item_type and isinstance(value, dict):\n                return matches\n            matches.extend(self.check_primitive_type(value, primitive_type, path))\n\n        return matches\n\n    def check(self, cfn, properties, specs, path):\n        \"\"\"Check itself\"\"\"\n        matches = []\n\n        for prop in properties:\n            if prop in specs:\n                primitive_type = specs.get(prop).get('PrimitiveType')\n                if not primitive_type:\n                    primitive_type = specs.get(prop).get('PrimitiveItemType')\n                if specs.get(prop).get('Type') in ['List', 'Map']:\n                    item_type = specs.get(prop).get('Type')\n                else:\n                    item_type = None\n                if primitive_type:\n                    matches.extend(\n                        cfn.check_value(\n                            properties, prop, path,\n                            check_value=self.check_value,\n                            primitive_type=primitive_type,\n                            item_type=item_type\n                        )\n                    )\n\n        return matches\n\n    def match_resource_sub_properties(self, properties, property_type, path, cfn):\n        \"\"\"Match for sub properties\"\"\"\n        matches = []\n\n        if self.property_specs.get(property_type, {}).get('Properties'):\n            property_specs = self.property_specs.get(property_type, {}).get('Properties', {})\n            matches.extend(self.check(cfn, properties, property_specs, path))\n\n        return matches\n\n    def match_resource_properties(self, properties, resource_type, path, cfn):\n        \"\"\"Check CloudFormation Properties\"\"\"\n        matches = []\n        resource_specs = self.resource_specs.get(resource_type, {}).get('Properties', {})\n        matches.extend(self.check(cfn, properties, resource_specs, path))\n\n        return matches\n", "path": "src/cfnlint/rules/resources/properties/ValuePrimitiveType.py"}]}