We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Custom Rule not working for boolean values
*cfn-lint version: (`cfn-lint --version`)* 0.54.4

*Description of issue.* Attempting to create a custom rule to detect KMS keys that do not have auto rotate enabled. I discovered https://github.com/aws-cloudformation/cfn-lint/issues/2185 which covers the inability to react to absence of a value, but I'm just having issues with booleans. I'm able to trip the rules, so I know custom rules are registering, but I'm unable to get it to trip only against KMS Key resources who's EnableKeyRotation is false

Please provide as much information as possible:
* Template linting issues:
  * Please provide a CloudFormation sample that generated the issue.
  * If present, please add links to the (official) documentation for clarification.
  * Validate if the issue still exists with the latest version of `cfn-lint` and/or the latest Spec files
* Feature request:
  * Please provide argumentation about the missing feature. Context is key!
Example cfn
```
---
AWSTemplateFormatVersion: '2010-09-09'
Resources:
  TestKey:
    Properties:
      EnableKeyRotation: false
      KeyPolicy:
        Statement:
        - Action: kms:*
          Effect: Allow
          Principal:
            AWS:
              Fn::Sub: arn:${AWS::Partition}:iam::${AWS::AccountId}:root
          Resource: "*"
          Sid: Enable key management, including IAM user permissions
        Version: '2012-10-17'
    Type: AWS::KMS::Key
```

rules file (showing different casings/quotings in case it's relevant)-
```
AWS::KMS::Key EnableKeyRotation == True ERROR "KMS keys should be configured to auto rotate"
AWS::KMS::Key EnableKeyRotation == true ERROR "KMS keys should be configured to auto rotate"
AWS::KMS::Key EnableKeyRotation == TRUE ERROR "KMS keys should be configured to auto rotate"
AWS::KMS::Key EnableKeyRotation == "True" ERROR "KMS keys should be configured to auto rotate"
AWS::KMS::Key EnableKeyRotation == "true" ERROR "KMS keys should be configured to auto rotate"
AWS::KMS::Key EnableKeyRotation == "TRUE" ERROR "KMS keys should be configured to auto rotate"
```

if I flip the rules to
```
AWS::KMS::Key EnableKeyRotation == false ERROR "KMS keys should be configured to auto rotate"
```
No change. But if I then flip the cfn template's EnableKeyRotation to `true` it is then flagged in violation

Cfn-lint uses the [CloudFormation Resource Specifications](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-resource-specification.html) as the base to do validation. These files are included as part of the application version. Please update to the latest version of `cfn-lint` or update the spec files manually (`cfn-lint -u`)


--- 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/custom/Operators.py`
Content:
```
1 """
2 Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 SPDX-License-Identifier: MIT-0
4 """
5 #pylint: disable=cyclic-import
6 import cfnlint.rules
7 
8 OPERATOR = [
9     'EQUALS',
10     'NOT_EQUALS',
11     '==',
12     '!=',
13     'IN',
14     'NOT_IN',
15     '>=',
16     '<=']
17 
18 
19 def CreateCustomRule(rule_id, resourceType, prop, value, error_message, description, shortdesc, rule_func):
20 
21     class CustomRule(cfnlint.rules.CloudFormationLintRule):
22 
23         def __init__(self, rule_id, resourceType, prop, value, error_message, description, shortdesc, rule_func):
24             super(CustomRule, self).__init__()
25             self.resource_property_types.append(resourceType)
26             self.id = rule_id
27             self.property_chain = prop.split('.')
28             self.property_value = value
29             self.error_message = error_message
30             self.description = description
31             self.shortdesc = shortdesc
32             self.rule_func = rule_func
33 
34         def _remaining_inset_properties(self, property_chain):
35             if len(property_chain) > 1:
36                 return property_chain[1:]
37 
38             return []
39 
40         def _check_value(self, value, path, property_chain, cfn):
41             matches = []
42             if property_chain:
43                 new_property_chain = self._remaining_inset_properties(property_chain)
44                 matches.extend(
45                     cfn.check_value(
46                         value, property_chain[0], path,
47                         check_value=self._check_value,
48                         property_chain=new_property_chain,
49                         cfn=cfn,
50                     ))
51                 return matches
52             if value:
53                 matches.extend(self.rule_func(value, self.property_value, path))
54             return matches
55 
56         def match_resource_properties(self, properties, _, path, cfn):
57             new_property_chain = self._remaining_inset_properties(self.property_chain)
58             return cfn.check_value(
59                 properties, self.property_chain[0], path,
60                 check_value=self._check_value,
61                 property_chain=new_property_chain,
62                 cfn=cfn,
63             )
64 
65     return CustomRule(rule_id, resourceType, prop, value, error_message, description, shortdesc, rule_func)
66 
67 
68 def CreateEqualsRule(rule_id, resourceType, prop, value, error_message):
69     def rule_func(value, expected_value, path):
70         matches = []
71         if str(value).strip().lower() != str(expected_value).strip().lower():
72             matches.append(cfnlint.rules.RuleMatch(
73                 path, error_message or 'Must equal check failed'))
74 
75         return matches
76 
77     return CreateCustomRule(
78         rule_id, resourceType, prop, value, error_message,
79         shortdesc='Custom rule to check for equal values',
80         description='Created from the custom rules parameter. This rule will check if a property value is equal to the specified value.',
81         rule_func=rule_func,
82     )
83 
84 
85 def CreateNotEqualsRule(rule_id, resourceType, prop, value, error_message):
86     def rule_func(value, expected_values, path):
87         matches = []
88         if str(value).strip().lower() == str(expected_values).strip().lower():
89             matches.append(cfnlint.rules.RuleMatch(
90                 path, error_message or 'Must not equal check failed'))
91 
92         return matches
93 
94     return CreateCustomRule(
95         rule_id, resourceType, prop, value, error_message,
96         shortdesc='Custom rule to check for not equal values',
97         description='Created from the custom rules parameter. This rule will check if a property value is NOT equal to the specified value.',
98         rule_func=rule_func,
99     )
100 
101 
102 def CreateGreaterRule(rule_id, resourceType, prop, value, error_message):
103     def rule_func(value, expected_value, path):
104         matches = []
105         if checkInt(value.strip()) and checkInt(str(expected_value).strip()):
106             if value.strip().lower() < str(expected_value).strip().lower():
107                 matches.append(cfnlint.rules.RuleMatch(
108                     path, error_message or 'Greater than check failed'))
109         else:
110             matches.append(cfnlint.rules.RuleMatch(
111                 path, error_message or 'Given values are not numeric'))
112 
113         return matches
114 
115     return CreateCustomRule(
116         rule_id, resourceType, prop, value, error_message,
117         shortdesc='Custom rule to check for if a value is greater than the specified value',
118         description='Created from the custom rules parameter. This rule will check if a property value is greater than the specified value.',
119         rule_func=rule_func,
120     )
121 
122 
123 def CreateLesserRule(rule_id, resourceType, prop, value, error_message):
124     def rule_func(value, expected_value, path):
125         matches = []
126         if checkInt(value.strip()) and checkInt(str(expected_value).strip()):
127             if value.strip().lower() > str(expected_value).strip().lower():
128                 matches.append(cfnlint.rules.RuleMatch(
129                     path, error_message or 'Lesser than check failed'))
130         else:
131             matches.append(cfnlint.rules.RuleMatch(
132                 path, error_message or 'Given values are not numeric'))
133 
134         return matches
135 
136     return CreateCustomRule(
137         rule_id, resourceType, prop, value, error_message,
138         shortdesc='Custom rule to check for if a value is lesser than the specified value',
139         description='Created from the custom rules parameter. This rule will check if a property value is lesser than the specified value.',
140         rule_func=rule_func,
141     )
142 
143 
144 def CreateInSetRule(rule_id, resourceType, prop, value, error_message):
145     def rule_func(value, expected_values, path):
146         matches = []
147         if value not in expected_values:
148             matches.append(cfnlint.rules.RuleMatch(path, error_message or 'In set check failed'))
149 
150         return matches
151 
152     return CreateCustomRule(
153         rule_id, resourceType, prop, value, error_message,
154         shortdesc='Custom rule to check for if a value exists in a list of specified values',
155         description='Created from the custom rules parameter. This rule will check if a property value exists inside a list of specified values.',
156         rule_func=rule_func,
157     )
158 
159 
160 def CreateNotInSetRule(rule_id, resourceType, prop, value, error_message):
161     def rule_func(value, expected_values, path):
162         matches = []
163         if value in expected_values:
164             matches.append(cfnlint.rules.RuleMatch(
165                 path, error_message or 'Not in set check failed'))
166 
167         return matches
168 
169     return CreateCustomRule(
170         rule_id, resourceType, prop, value, error_message,
171         shortdesc='Custom rule to check for if a value does not exist in a list of specified values',
172         description='Created from the custom rules parameter. This rule will check if a property value does not exist inside a list of specified values.',
173         rule_func=rule_func,
174     )
175 
176 
177 def CreateInvalidRule(rule_id, operator):
178     class InvalidRule(cfnlint.rules.CloudFormationLintRule):
179 
180         def __init__(self, rule_id, operator):
181             super(InvalidRule, self).__init__()
182             self.id = rule_id
183             self.operator = operator
184             self.description = 'Created from the custom rule parameter. This rule is the result of an invalid configuration of a custom rule.'
185             self.shortdesc = 'Invalid custom rule configuration'
186 
187         def match(self, _):
188             message = '"{0}" not in supported operators: [{1}]'
189             return [
190                 cfnlint.rules.RuleMatch(
191                     [], message.format(str(self.operator), ', '.join(OPERATOR)))
192             ]
193 
194     return InvalidRule(rule_id, operator)
195 
196 
197 def checkInt(i):
198     """ Python 2.7 Compatibility - There is no isnumeric() method """
199     try:
200         int(i)
201         return True
202     except ValueError:
203         return False
204
```
--- 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/custom/Operators.py b/src/cfnlint/rules/custom/Operators.py
--- a/src/cfnlint/rules/custom/Operators.py
+++ b/src/cfnlint/rules/custom/Operators.py
@@ -49,7 +49,7 @@
                         cfn=cfn,
                     ))
                 return matches
-            if value:
+            if value is not None:
                 matches.extend(self.rule_func(value, self.property_value, path))
             return matches

{"golden_diff": "diff --git a/src/cfnlint/rules/custom/Operators.py b/src/cfnlint/rules/custom/Operators.py\n--- a/src/cfnlint/rules/custom/Operators.py\n+++ b/src/cfnlint/rules/custom/Operators.py\n@@ -49,7 +49,7 @@\n                         cfn=cfn,\n                     ))\n                 return matches\n-            if value:\n+            if value is not None:\n                 matches.extend(self.rule_func(value, self.property_value, path))\n             return matches\n", "issue": "Custom Rule not working for boolean values\n*cfn-lint version: (`cfn-lint --version`)* 0.54.4\r\n\r\n*Description of issue.* Attempting to create a custom rule to detect KMS keys that do not have auto rotate enabled. I discovered https://github.com/aws-cloudformation/cfn-lint/issues/2185 which covers the inability to react to absence of a value, but I'm just having issues with booleans. I'm able to trip the rules, so I know custom rules are registering, but I'm unable to get it to trip only against KMS Key resources who's EnableKeyRotation is false\r\n\r\nPlease provide as much information as possible:\r\n* Template linting issues:\r\n  * Please provide a CloudFormation sample that generated the issue.\r\n  * If present, please add links to the (official) documentation for clarification.\r\n  * Validate if the issue still exists with the latest version of `cfn-lint` and/or the latest Spec files\r\n* Feature request:\r\n  * Please provide argumentation about the missing feature. Context is key!\r\nExample cfn\r\n```\r\n---\r\nAWSTemplateFormatVersion: '2010-09-09'\r\nResources:\r\n  TestKey:\r\n    Properties:\r\n      EnableKeyRotation: false\r\n      KeyPolicy:\r\n        Statement:\r\n        - Action: kms:*\r\n          Effect: Allow\r\n          Principal:\r\n            AWS:\r\n              Fn::Sub: arn:${AWS::Partition}:iam::${AWS::AccountId}:root\r\n          Resource: \"*\"\r\n          Sid: Enable key management, including IAM user permissions\r\n        Version: '2012-10-17'\r\n    Type: AWS::KMS::Key\r\n```\r\n\r\nrules file (showing different casings/quotings in case it's relevant)-\r\n```\r\nAWS::KMS::Key EnableKeyRotation == True ERROR \"KMS keys should be configured to auto rotate\"\r\nAWS::KMS::Key EnableKeyRotation == true ERROR \"KMS keys should be configured to auto rotate\"\r\nAWS::KMS::Key EnableKeyRotation == TRUE ERROR \"KMS keys should be configured to auto rotate\"\r\nAWS::KMS::Key EnableKeyRotation == \"True\" ERROR \"KMS keys should be configured to auto rotate\"\r\nAWS::KMS::Key EnableKeyRotation == \"true\" ERROR \"KMS keys should be configured to auto rotate\"\r\nAWS::KMS::Key EnableKeyRotation == \"TRUE\" ERROR \"KMS keys should be configured to auto rotate\"\r\n```\r\n\r\nif I flip the rules to\r\n```\r\nAWS::KMS::Key EnableKeyRotation == false ERROR \"KMS keys should be configured to auto rotate\"\r\n```\r\nNo change. But if I then flip the cfn template's EnableKeyRotation to `true` it is then flagged in violation\r\n\r\nCfn-lint uses the [CloudFormation Resource Specifications](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-resource-specification.html) as the base to do validation. These files are included as part of the application version. Please update to the latest version of `cfn-lint` or update the spec files manually (`cfn-lint -u`)\r\n\n", "before_files": [{"content": "\"\"\"\nCopyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\nSPDX-License-Identifier: MIT-0\n\"\"\"\n#pylint: disable=cyclic-import\nimport cfnlint.rules\n\nOPERATOR = [\n    'EQUALS',\n    'NOT_EQUALS',\n    '==',\n    '!=',\n    'IN',\n    'NOT_IN',\n    '>=',\n    '<=']\n\n\ndef CreateCustomRule(rule_id, resourceType, prop, value, error_message, description, shortdesc, rule_func):\n\n    class CustomRule(cfnlint.rules.CloudFormationLintRule):\n\n        def __init__(self, rule_id, resourceType, prop, value, error_message, description, shortdesc, rule_func):\n            super(CustomRule, self).__init__()\n            self.resource_property_types.append(resourceType)\n            self.id = rule_id\n            self.property_chain = prop.split('.')\n            self.property_value = value\n            self.error_message = error_message\n            self.description = description\n            self.shortdesc = shortdesc\n            self.rule_func = rule_func\n\n        def _remaining_inset_properties(self, property_chain):\n            if len(property_chain) > 1:\n                return property_chain[1:]\n\n            return []\n\n        def _check_value(self, value, path, property_chain, cfn):\n            matches = []\n            if property_chain:\n                new_property_chain = self._remaining_inset_properties(property_chain)\n                matches.extend(\n                    cfn.check_value(\n                        value, property_chain[0], path,\n                        check_value=self._check_value,\n                        property_chain=new_property_chain,\n                        cfn=cfn,\n                    ))\n                return matches\n            if value:\n                matches.extend(self.rule_func(value, self.property_value, path))\n            return matches\n\n        def match_resource_properties(self, properties, _, path, cfn):\n            new_property_chain = self._remaining_inset_properties(self.property_chain)\n            return cfn.check_value(\n                properties, self.property_chain[0], path,\n                check_value=self._check_value,\n                property_chain=new_property_chain,\n                cfn=cfn,\n            )\n\n    return CustomRule(rule_id, resourceType, prop, value, error_message, description, shortdesc, rule_func)\n\n\ndef CreateEqualsRule(rule_id, resourceType, prop, value, error_message):\n    def rule_func(value, expected_value, path):\n        matches = []\n        if str(value).strip().lower() != str(expected_value).strip().lower():\n            matches.append(cfnlint.rules.RuleMatch(\n                path, error_message or 'Must equal check failed'))\n\n        return matches\n\n    return CreateCustomRule(\n        rule_id, resourceType, prop, value, error_message,\n        shortdesc='Custom rule to check for equal values',\n        description='Created from the custom rules parameter. This rule will check if a property value is equal to the specified value.',\n        rule_func=rule_func,\n    )\n\n\ndef CreateNotEqualsRule(rule_id, resourceType, prop, value, error_message):\n    def rule_func(value, expected_values, path):\n        matches = []\n        if str(value).strip().lower() == str(expected_values).strip().lower():\n            matches.append(cfnlint.rules.RuleMatch(\n                path, error_message or 'Must not equal check failed'))\n\n        return matches\n\n    return CreateCustomRule(\n        rule_id, resourceType, prop, value, error_message,\n        shortdesc='Custom rule to check for not equal values',\n        description='Created from the custom rules parameter. This rule will check if a property value is NOT equal to the specified value.',\n        rule_func=rule_func,\n    )\n\n\ndef CreateGreaterRule(rule_id, resourceType, prop, value, error_message):\n    def rule_func(value, expected_value, path):\n        matches = []\n        if checkInt(value.strip()) and checkInt(str(expected_value).strip()):\n            if value.strip().lower() < str(expected_value).strip().lower():\n                matches.append(cfnlint.rules.RuleMatch(\n                    path, error_message or 'Greater than check failed'))\n        else:\n            matches.append(cfnlint.rules.RuleMatch(\n                path, error_message or 'Given values are not numeric'))\n\n        return matches\n\n    return CreateCustomRule(\n        rule_id, resourceType, prop, value, error_message,\n        shortdesc='Custom rule to check for if a value is greater than the specified value',\n        description='Created from the custom rules parameter. This rule will check if a property value is greater than the specified value.',\n        rule_func=rule_func,\n    )\n\n\ndef CreateLesserRule(rule_id, resourceType, prop, value, error_message):\n    def rule_func(value, expected_value, path):\n        matches = []\n        if checkInt(value.strip()) and checkInt(str(expected_value).strip()):\n            if value.strip().lower() > str(expected_value).strip().lower():\n                matches.append(cfnlint.rules.RuleMatch(\n                    path, error_message or 'Lesser than check failed'))\n        else:\n            matches.append(cfnlint.rules.RuleMatch(\n                path, error_message or 'Given values are not numeric'))\n\n        return matches\n\n    return CreateCustomRule(\n        rule_id, resourceType, prop, value, error_message,\n        shortdesc='Custom rule to check for if a value is lesser than the specified value',\n        description='Created from the custom rules parameter. This rule will check if a property value is lesser than the specified value.',\n        rule_func=rule_func,\n    )\n\n\ndef CreateInSetRule(rule_id, resourceType, prop, value, error_message):\n    def rule_func(value, expected_values, path):\n        matches = []\n        if value not in expected_values:\n            matches.append(cfnlint.rules.RuleMatch(path, error_message or 'In set check failed'))\n\n        return matches\n\n    return CreateCustomRule(\n        rule_id, resourceType, prop, value, error_message,\n        shortdesc='Custom rule to check for if a value exists in a list of specified values',\n        description='Created from the custom rules parameter. This rule will check if a property value exists inside a list of specified values.',\n        rule_func=rule_func,\n    )\n\n\ndef CreateNotInSetRule(rule_id, resourceType, prop, value, error_message):\n    def rule_func(value, expected_values, path):\n        matches = []\n        if value in expected_values:\n            matches.append(cfnlint.rules.RuleMatch(\n                path, error_message or 'Not in set check failed'))\n\n        return matches\n\n    return CreateCustomRule(\n        rule_id, resourceType, prop, value, error_message,\n        shortdesc='Custom rule to check for if a value does not exist in a list of specified values',\n        description='Created from the custom rules parameter. This rule will check if a property value does not exist inside a list of specified values.',\n        rule_func=rule_func,\n    )\n\n\ndef CreateInvalidRule(rule_id, operator):\n    class InvalidRule(cfnlint.rules.CloudFormationLintRule):\n\n        def __init__(self, rule_id, operator):\n            super(InvalidRule, self).__init__()\n            self.id = rule_id\n            self.operator = operator\n            self.description = 'Created from the custom rule parameter. This rule is the result of an invalid configuration of a custom rule.'\n            self.shortdesc = 'Invalid custom rule configuration'\n\n        def match(self, _):\n            message = '\"{0}\" not in supported operators: [{1}]'\n            return [\n                cfnlint.rules.RuleMatch(\n                    [], message.format(str(self.operator), ', '.join(OPERATOR)))\n            ]\n\n    return InvalidRule(rule_id, operator)\n\n\ndef checkInt(i):\n    \"\"\" Python 2.7 Compatibility - There is no isnumeric() method \"\"\"\n    try:\n        int(i)\n        return True\n    except ValueError:\n        return False\n", "path": "src/cfnlint/rules/custom/Operators.py"}], "after_files": [{"content": "\"\"\"\nCopyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\nSPDX-License-Identifier: MIT-0\n\"\"\"\n#pylint: disable=cyclic-import\nimport cfnlint.rules\n\nOPERATOR = [\n    'EQUALS',\n    'NOT_EQUALS',\n    '==',\n    '!=',\n    'IN',\n    'NOT_IN',\n    '>=',\n    '<=']\n\n\ndef CreateCustomRule(rule_id, resourceType, prop, value, error_message, description, shortdesc, rule_func):\n\n    class CustomRule(cfnlint.rules.CloudFormationLintRule):\n\n        def __init__(self, rule_id, resourceType, prop, value, error_message, description, shortdesc, rule_func):\n            super(CustomRule, self).__init__()\n            self.resource_property_types.append(resourceType)\n            self.id = rule_id\n            self.property_chain = prop.split('.')\n            self.property_value = value\n            self.error_message = error_message\n            self.description = description\n            self.shortdesc = shortdesc\n            self.rule_func = rule_func\n\n        def _remaining_inset_properties(self, property_chain):\n            if len(property_chain) > 1:\n                return property_chain[1:]\n\n            return []\n\n        def _check_value(self, value, path, property_chain, cfn):\n            matches = []\n            if property_chain:\n                new_property_chain = self._remaining_inset_properties(property_chain)\n                matches.extend(\n                    cfn.check_value(\n                        value, property_chain[0], path,\n                        check_value=self._check_value,\n                        property_chain=new_property_chain,\n                        cfn=cfn,\n                    ))\n                return matches\n            if value is not None:\n                matches.extend(self.rule_func(value, self.property_value, path))\n            return matches\n\n        def match_resource_properties(self, properties, _, path, cfn):\n            new_property_chain = self._remaining_inset_properties(self.property_chain)\n            return cfn.check_value(\n                properties, self.property_chain[0], path,\n                check_value=self._check_value,\n                property_chain=new_property_chain,\n                cfn=cfn,\n            )\n\n    return CustomRule(rule_id, resourceType, prop, value, error_message, description, shortdesc, rule_func)\n\n\ndef CreateEqualsRule(rule_id, resourceType, prop, value, error_message):\n    def rule_func(value, expected_value, path):\n        matches = []\n        if str(value).strip().lower() != str(expected_value).strip().lower():\n            matches.append(cfnlint.rules.RuleMatch(\n                path, error_message or 'Must equal check failed'))\n\n        return matches\n\n    return CreateCustomRule(\n        rule_id, resourceType, prop, value, error_message,\n        shortdesc='Custom rule to check for equal values',\n        description='Created from the custom rules parameter. This rule will check if a property value is equal to the specified value.',\n        rule_func=rule_func,\n    )\n\n\ndef CreateNotEqualsRule(rule_id, resourceType, prop, value, error_message):\n    def rule_func(value, expected_values, path):\n        matches = []\n        if str(value).strip().lower() == str(expected_values).strip().lower():\n            matches.append(cfnlint.rules.RuleMatch(\n                path, error_message or 'Must not equal check failed'))\n\n        return matches\n\n    return CreateCustomRule(\n        rule_id, resourceType, prop, value, error_message,\n        shortdesc='Custom rule to check for not equal values',\n        description='Created from the custom rules parameter. This rule will check if a property value is NOT equal to the specified value.',\n        rule_func=rule_func,\n    )\n\n\ndef CreateGreaterRule(rule_id, resourceType, prop, value, error_message):\n    def rule_func(value, expected_value, path):\n        matches = []\n        if checkInt(value.strip()) and checkInt(str(expected_value).strip()):\n            if value.strip().lower() < str(expected_value).strip().lower():\n                matches.append(cfnlint.rules.RuleMatch(\n                    path, error_message or 'Greater than check failed'))\n        else:\n            matches.append(cfnlint.rules.RuleMatch(\n                path, error_message or 'Given values are not numeric'))\n\n        return matches\n\n    return CreateCustomRule(\n        rule_id, resourceType, prop, value, error_message,\n        shortdesc='Custom rule to check for if a value is greater than the specified value',\n        description='Created from the custom rules parameter. This rule will check if a property value is greater than the specified value.',\n        rule_func=rule_func,\n    )\n\n\ndef CreateLesserRule(rule_id, resourceType, prop, value, error_message):\n    def rule_func(value, expected_value, path):\n        matches = []\n        if checkInt(value.strip()) and checkInt(str(expected_value).strip()):\n            if value.strip().lower() > str(expected_value).strip().lower():\n                matches.append(cfnlint.rules.RuleMatch(\n                    path, error_message or 'Lesser than check failed'))\n        else:\n            matches.append(cfnlint.rules.RuleMatch(\n                path, error_message or 'Given values are not numeric'))\n\n        return matches\n\n    return CreateCustomRule(\n        rule_id, resourceType, prop, value, error_message,\n        shortdesc='Custom rule to check for if a value is lesser than the specified value',\n        description='Created from the custom rules parameter. This rule will check if a property value is lesser than the specified value.',\n        rule_func=rule_func,\n    )\n\n\ndef CreateInSetRule(rule_id, resourceType, prop, value, error_message):\n    def rule_func(value, expected_values, path):\n        matches = []\n        if value not in expected_values:\n            matches.append(cfnlint.rules.RuleMatch(path, error_message or 'In set check failed'))\n\n        return matches\n\n    return CreateCustomRule(\n        rule_id, resourceType, prop, value, error_message,\n        shortdesc='Custom rule to check for if a value exists in a list of specified values',\n        description='Created from the custom rules parameter. This rule will check if a property value exists inside a list of specified values.',\n        rule_func=rule_func,\n    )\n\n\ndef CreateNotInSetRule(rule_id, resourceType, prop, value, error_message):\n    def rule_func(value, expected_values, path):\n        matches = []\n        if value in expected_values:\n            matches.append(cfnlint.rules.RuleMatch(\n                path, error_message or 'Not in set check failed'))\n\n        return matches\n\n    return CreateCustomRule(\n        rule_id, resourceType, prop, value, error_message,\n        shortdesc='Custom rule to check for if a value does not exist in a list of specified values',\n        description='Created from the custom rules parameter. This rule will check if a property value does not exist inside a list of specified values.',\n        rule_func=rule_func,\n    )\n\n\ndef CreateInvalidRule(rule_id, operator):\n    class InvalidRule(cfnlint.rules.CloudFormationLintRule):\n\n        def __init__(self, rule_id, operator):\n            super(InvalidRule, self).__init__()\n            self.id = rule_id\n            self.operator = operator\n            self.description = 'Created from the custom rule parameter. This rule is the result of an invalid configuration of a custom rule.'\n            self.shortdesc = 'Invalid custom rule configuration'\n\n        def match(self, _):\n            message = '\"{0}\" not in supported operators: [{1}]'\n            return [\n                cfnlint.rules.RuleMatch(\n                    [], message.format(str(self.operator), ', '.join(OPERATOR)))\n            ]\n\n    return InvalidRule(rule_id, operator)\n\n\ndef checkInt(i):\n    \"\"\" Python 2.7 Compatibility - There is no isnumeric() method \"\"\"\n    try:\n        int(i)\n        return True\n    except ValueError:\n        return False\n", "path": "src/cfnlint/rules/custom/Operators.py"}]}