We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Validator issue in Dynamodb
The validator added in #1243 will fail if you use an If for a property

Code:
```
TableName=If("useTableName", Ref(table_name), Ref(AWS_NO_VALUE)),
```

Error:

```
  File "e:\github\troposphere\troposphere\__init__.py", line 247, in to_dict
    self.validate()
  File "e:\github\troposphere\troposphere\dynamodb.py", line 139, in validate
    tput_props.extend([x.properties for x in indexes])
RuntimeError: Failed to build JSON for template DynamoDB: 'If' object has no attribute 'properties'
```

Removing the following line resolves the issue:
https://github.com/cloudtools/troposphere/blob/master/troposphere/dynamodb.py#L139

From what I can tell the validator does not take into account using an `If` to determine if a property is set or if it is set to `AWS_NO_VALUE`.





--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `troposphere/dynamodb.py`
Content:
```
1 # Copyright (c) 2012-2013, Mark Peek <mark@peek.org>
2 # All rights reserved.
3 #
4 # See LICENSE file for full license.
5 
6 from . import AWSObject, AWSProperty, AWSHelperFn, If, Tags
7 from .validators import boolean
8 
9 
10 def attribute_type_validator(x):
11     valid_types = ["S", "N", "B"]
12     if x not in valid_types:
13         raise ValueError("AttributeType must be one of: %s" %
14                          ", ".join(valid_types))
15     return x
16 
17 
18 def key_type_validator(x):
19     valid_types = ["HASH", "RANGE"]
20     if x not in valid_types:
21         raise ValueError("KeyType must be one of: %s" % ", ".join(valid_types))
22     return x
23 
24 
25 def projection_type_validator(x):
26     valid_types = ["KEYS_ONLY", "INCLUDE", "ALL"]
27     if x not in valid_types:
28         raise ValueError("ProjectionType must be one of: %s" %
29                          ", ".join(valid_types))
30     return x
31 
32 
33 def billing_mode_validator(x):
34     valid_modes = ['PROVISIONED', 'PAY_PER_REQUEST']
35     if x not in valid_modes:
36         raise ValueError("Table billing mode must be one of: %s" %
37                          ", ".join(valid_modes))
38     return x
39 
40 
41 class AttributeDefinition(AWSProperty):
42     props = {
43         "AttributeName": (basestring, True),
44         "AttributeType": (attribute_type_validator, True),
45     }
46 
47 
48 class KeySchema(AWSProperty):
49     props = {
50         "AttributeName": (basestring, True),
51         "KeyType": (key_type_validator, True)
52     }
53 
54 
55 class Key(KeySchema):
56     """ For backwards compatibility. """
57     pass
58 
59 
60 class ProvisionedThroughput(AWSProperty):
61     props = {
62         "ReadCapacityUnits": (int, True),
63         "WriteCapacityUnits": (int, True),
64     }
65 
66 
67 class Projection(AWSProperty):
68     props = {
69         "NonKeyAttributes": ([basestring], False),
70         "ProjectionType": (projection_type_validator, False)
71     }
72 
73 
74 class SSESpecification(AWSProperty):
75     props = {
76         "SSEEnabled": (boolean, True),
77     }
78 
79 
80 class GlobalSecondaryIndex(AWSProperty):
81     props = {
82         "IndexName": (basestring, True),
83         "KeySchema": ([KeySchema], True),
84         "Projection": (Projection, True),
85         "ProvisionedThroughput": (ProvisionedThroughput, False)
86     }
87 
88 
89 class LocalSecondaryIndex(AWSProperty):
90     props = {
91         "IndexName": (basestring, True),
92         "KeySchema": ([KeySchema], True),
93         "Projection": (Projection, True),
94     }
95 
96 
97 class PointInTimeRecoverySpecification(AWSProperty):
98     props = {
99         'PointInTimeRecoveryEnabled': (boolean, False),
100     }
101 
102 
103 class StreamSpecification(AWSProperty):
104     props = {
105         'StreamViewType': (basestring, True),
106     }
107 
108 
109 class TimeToLiveSpecification(AWSProperty):
110     props = {
111         'AttributeName': (basestring, True),
112         'Enabled': (boolean, True),
113     }
114 
115 
116 class Table(AWSObject):
117     resource_type = "AWS::DynamoDB::Table"
118 
119     props = {
120         'AttributeDefinitions': ([AttributeDefinition], True),
121         'BillingMode': (billing_mode_validator, False),
122         'GlobalSecondaryIndexes': ([GlobalSecondaryIndex], False),
123         'KeySchema': ([KeySchema], True),
124         'LocalSecondaryIndexes': ([LocalSecondaryIndex], False),
125         'PointInTimeRecoverySpecification':
126             (PointInTimeRecoverySpecification, False),
127         'ProvisionedThroughput': (ProvisionedThroughput, False),
128         'SSESpecification': (SSESpecification, False),
129         'StreamSpecification': (StreamSpecification, False),
130         'TableName': (basestring, False),
131         'Tags': (Tags, False),
132         'TimeToLiveSpecification': (TimeToLiveSpecification, False),
133     }
134 
135     def validate(self):
136         billing_mode = self.properties.get('BillingMode', 'PROVISIONED')
137         indexes = self.properties.get('GlobalSecondaryIndexes', [])
138         tput_props = [self.properties]
139         tput_props.extend([x.properties for x in indexes])
140 
141         def check_if_all(name, props):
142             validated = []
143             for prop in props:
144                 is_helper = isinstance(prop.get(name), AWSHelperFn)
145                 validated.append(name in prop or is_helper)
146             return all(validated)
147 
148         def check_any(name, props):
149             validated = []
150             for prop in props:
151                 is_helper = isinstance(prop.get(name), AWSHelperFn)
152                 validated.append(name in prop and not is_helper)
153             return any(validated)
154 
155         if isinstance(billing_mode, If):
156             if check_any('ProvisionedThroughput', tput_props):
157                 raise ValueError(
158                     'Table billing mode is per-request. '
159                     'ProvisionedThroughput property is mutually exclusive')
160             return
161 
162         if billing_mode == 'PROVISIONED':
163             if not check_if_all('ProvisionedThroughput', tput_props):
164                 raise ValueError(
165                     'Table billing mode is provisioned. '
166                     'ProvisionedThroughput required if available')
167         elif billing_mode == 'PAY_PER_REQUEST':
168             if check_any('ProvisionedThroughput', tput_props):
169                 raise ValueError(
170                     'Table billing mode is per-request. '
171                     'ProvisionedThroughput property is mutually exclusive')
172
```
--- 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/troposphere/dynamodb.py b/troposphere/dynamodb.py
--- a/troposphere/dynamodb.py
+++ b/troposphere/dynamodb.py
@@ -136,7 +136,9 @@
         billing_mode = self.properties.get('BillingMode', 'PROVISIONED')
         indexes = self.properties.get('GlobalSecondaryIndexes', [])
         tput_props = [self.properties]
-        tput_props.extend([x.properties for x in indexes])
+        tput_props.extend([
+            x.properties for x in indexes if not isinstance(x, AWSHelperFn)
+        ])
 
         def check_if_all(name, props):
             validated = []

{"golden_diff": "diff --git a/troposphere/dynamodb.py b/troposphere/dynamodb.py\n--- a/troposphere/dynamodb.py\n+++ b/troposphere/dynamodb.py\n@@ -136,7 +136,9 @@\n         billing_mode = self.properties.get('BillingMode', 'PROVISIONED')\n         indexes = self.properties.get('GlobalSecondaryIndexes', [])\n         tput_props = [self.properties]\n-        tput_props.extend([x.properties for x in indexes])\n+        tput_props.extend([\n+            x.properties for x in indexes if not isinstance(x, AWSHelperFn)\n+        ])\n \n         def check_if_all(name, props):\n             validated = []\n", "issue": "Validator issue in Dynamodb\nThe validator added in #1243 will fail if you use an If for a property\r\n\r\nCode:\r\n```\r\nTableName=If(\"useTableName\", Ref(table_name), Ref(AWS_NO_VALUE)),\r\n```\r\n\r\nError:\r\n\r\n```\r\n  File \"e:\\github\\troposphere\\troposphere\\__init__.py\", line 247, in to_dict\r\n    self.validate()\r\n  File \"e:\\github\\troposphere\\troposphere\\dynamodb.py\", line 139, in validate\r\n    tput_props.extend([x.properties for x in indexes])\r\nRuntimeError: Failed to build JSON for template DynamoDB: 'If' object has no attribute 'properties'\r\n```\r\n\r\nRemoving the following line resolves the issue:\r\nhttps://github.com/cloudtools/troposphere/blob/master/troposphere/dynamodb.py#L139\r\n\r\nFrom what I can tell the validator does not take into account using an `If` to determine if a property is set or if it is set to `AWS_NO_VALUE`.\r\n\r\n\r\n\r\n\n", "before_files": [{"content": "# Copyright (c) 2012-2013, Mark Peek <mark@peek.org>\n# All rights reserved.\n#\n# See LICENSE file for full license.\n\nfrom . import AWSObject, AWSProperty, AWSHelperFn, If, Tags\nfrom .validators import boolean\n\n\ndef attribute_type_validator(x):\n    valid_types = [\"S\", \"N\", \"B\"]\n    if x not in valid_types:\n        raise ValueError(\"AttributeType must be one of: %s\" %\n                         \", \".join(valid_types))\n    return x\n\n\ndef key_type_validator(x):\n    valid_types = [\"HASH\", \"RANGE\"]\n    if x not in valid_types:\n        raise ValueError(\"KeyType must be one of: %s\" % \", \".join(valid_types))\n    return x\n\n\ndef projection_type_validator(x):\n    valid_types = [\"KEYS_ONLY\", \"INCLUDE\", \"ALL\"]\n    if x not in valid_types:\n        raise ValueError(\"ProjectionType must be one of: %s\" %\n                         \", \".join(valid_types))\n    return x\n\n\ndef billing_mode_validator(x):\n    valid_modes = ['PROVISIONED', 'PAY_PER_REQUEST']\n    if x not in valid_modes:\n        raise ValueError(\"Table billing mode must be one of: %s\" %\n                         \", \".join(valid_modes))\n    return x\n\n\nclass AttributeDefinition(AWSProperty):\n    props = {\n        \"AttributeName\": (basestring, True),\n        \"AttributeType\": (attribute_type_validator, True),\n    }\n\n\nclass KeySchema(AWSProperty):\n    props = {\n        \"AttributeName\": (basestring, True),\n        \"KeyType\": (key_type_validator, True)\n    }\n\n\nclass Key(KeySchema):\n    \"\"\" For backwards compatibility. \"\"\"\n    pass\n\n\nclass ProvisionedThroughput(AWSProperty):\n    props = {\n        \"ReadCapacityUnits\": (int, True),\n        \"WriteCapacityUnits\": (int, True),\n    }\n\n\nclass Projection(AWSProperty):\n    props = {\n        \"NonKeyAttributes\": ([basestring], False),\n        \"ProjectionType\": (projection_type_validator, False)\n    }\n\n\nclass SSESpecification(AWSProperty):\n    props = {\n        \"SSEEnabled\": (boolean, True),\n    }\n\n\nclass GlobalSecondaryIndex(AWSProperty):\n    props = {\n        \"IndexName\": (basestring, True),\n        \"KeySchema\": ([KeySchema], True),\n        \"Projection\": (Projection, True),\n        \"ProvisionedThroughput\": (ProvisionedThroughput, False)\n    }\n\n\nclass LocalSecondaryIndex(AWSProperty):\n    props = {\n        \"IndexName\": (basestring, True),\n        \"KeySchema\": ([KeySchema], True),\n        \"Projection\": (Projection, True),\n    }\n\n\nclass PointInTimeRecoverySpecification(AWSProperty):\n    props = {\n        'PointInTimeRecoveryEnabled': (boolean, False),\n    }\n\n\nclass StreamSpecification(AWSProperty):\n    props = {\n        'StreamViewType': (basestring, True),\n    }\n\n\nclass TimeToLiveSpecification(AWSProperty):\n    props = {\n        'AttributeName': (basestring, True),\n        'Enabled': (boolean, True),\n    }\n\n\nclass Table(AWSObject):\n    resource_type = \"AWS::DynamoDB::Table\"\n\n    props = {\n        'AttributeDefinitions': ([AttributeDefinition], True),\n        'BillingMode': (billing_mode_validator, False),\n        'GlobalSecondaryIndexes': ([GlobalSecondaryIndex], False),\n        'KeySchema': ([KeySchema], True),\n        'LocalSecondaryIndexes': ([LocalSecondaryIndex], False),\n        'PointInTimeRecoverySpecification':\n            (PointInTimeRecoverySpecification, False),\n        'ProvisionedThroughput': (ProvisionedThroughput, False),\n        'SSESpecification': (SSESpecification, False),\n        'StreamSpecification': (StreamSpecification, False),\n        'TableName': (basestring, False),\n        'Tags': (Tags, False),\n        'TimeToLiveSpecification': (TimeToLiveSpecification, False),\n    }\n\n    def validate(self):\n        billing_mode = self.properties.get('BillingMode', 'PROVISIONED')\n        indexes = self.properties.get('GlobalSecondaryIndexes', [])\n        tput_props = [self.properties]\n        tput_props.extend([x.properties for x in indexes])\n\n        def check_if_all(name, props):\n            validated = []\n            for prop in props:\n                is_helper = isinstance(prop.get(name), AWSHelperFn)\n                validated.append(name in prop or is_helper)\n            return all(validated)\n\n        def check_any(name, props):\n            validated = []\n            for prop in props:\n                is_helper = isinstance(prop.get(name), AWSHelperFn)\n                validated.append(name in prop and not is_helper)\n            return any(validated)\n\n        if isinstance(billing_mode, If):\n            if check_any('ProvisionedThroughput', tput_props):\n                raise ValueError(\n                    'Table billing mode is per-request. '\n                    'ProvisionedThroughput property is mutually exclusive')\n            return\n\n        if billing_mode == 'PROVISIONED':\n            if not check_if_all('ProvisionedThroughput', tput_props):\n                raise ValueError(\n                    'Table billing mode is provisioned. '\n                    'ProvisionedThroughput required if available')\n        elif billing_mode == 'PAY_PER_REQUEST':\n            if check_any('ProvisionedThroughput', tput_props):\n                raise ValueError(\n                    'Table billing mode is per-request. '\n                    'ProvisionedThroughput property is mutually exclusive')\n", "path": "troposphere/dynamodb.py"}], "after_files": [{"content": "# Copyright (c) 2012-2013, Mark Peek <mark@peek.org>\n# All rights reserved.\n#\n# See LICENSE file for full license.\n\nfrom . import AWSObject, AWSProperty, AWSHelperFn, If, Tags\nfrom .validators import boolean\n\n\ndef attribute_type_validator(x):\n    valid_types = [\"S\", \"N\", \"B\"]\n    if x not in valid_types:\n        raise ValueError(\"AttributeType must be one of: %s\" %\n                         \", \".join(valid_types))\n    return x\n\n\ndef key_type_validator(x):\n    valid_types = [\"HASH\", \"RANGE\"]\n    if x not in valid_types:\n        raise ValueError(\"KeyType must be one of: %s\" % \", \".join(valid_types))\n    return x\n\n\ndef projection_type_validator(x):\n    valid_types = [\"KEYS_ONLY\", \"INCLUDE\", \"ALL\"]\n    if x not in valid_types:\n        raise ValueError(\"ProjectionType must be one of: %s\" %\n                         \", \".join(valid_types))\n    return x\n\n\ndef billing_mode_validator(x):\n    valid_modes = ['PROVISIONED', 'PAY_PER_REQUEST']\n    if x not in valid_modes:\n        raise ValueError(\"Table billing mode must be one of: %s\" %\n                         \", \".join(valid_modes))\n    return x\n\n\nclass AttributeDefinition(AWSProperty):\n    props = {\n        \"AttributeName\": (basestring, True),\n        \"AttributeType\": (attribute_type_validator, True),\n    }\n\n\nclass KeySchema(AWSProperty):\n    props = {\n        \"AttributeName\": (basestring, True),\n        \"KeyType\": (key_type_validator, True)\n    }\n\n\nclass Key(KeySchema):\n    \"\"\" For backwards compatibility. \"\"\"\n    pass\n\n\nclass ProvisionedThroughput(AWSProperty):\n    props = {\n        \"ReadCapacityUnits\": (int, True),\n        \"WriteCapacityUnits\": (int, True),\n    }\n\n\nclass Projection(AWSProperty):\n    props = {\n        \"NonKeyAttributes\": ([basestring], False),\n        \"ProjectionType\": (projection_type_validator, False)\n    }\n\n\nclass SSESpecification(AWSProperty):\n    props = {\n        \"SSEEnabled\": (boolean, True),\n    }\n\n\nclass GlobalSecondaryIndex(AWSProperty):\n    props = {\n        \"IndexName\": (basestring, True),\n        \"KeySchema\": ([KeySchema], True),\n        \"Projection\": (Projection, True),\n        \"ProvisionedThroughput\": (ProvisionedThroughput, False)\n    }\n\n\nclass LocalSecondaryIndex(AWSProperty):\n    props = {\n        \"IndexName\": (basestring, True),\n        \"KeySchema\": ([KeySchema], True),\n        \"Projection\": (Projection, True),\n    }\n\n\nclass PointInTimeRecoverySpecification(AWSProperty):\n    props = {\n        'PointInTimeRecoveryEnabled': (boolean, False),\n    }\n\n\nclass StreamSpecification(AWSProperty):\n    props = {\n        'StreamViewType': (basestring, True),\n    }\n\n\nclass TimeToLiveSpecification(AWSProperty):\n    props = {\n        'AttributeName': (basestring, True),\n        'Enabled': (boolean, True),\n    }\n\n\nclass Table(AWSObject):\n    resource_type = \"AWS::DynamoDB::Table\"\n\n    props = {\n        'AttributeDefinitions': ([AttributeDefinition], True),\n        'BillingMode': (billing_mode_validator, False),\n        'GlobalSecondaryIndexes': ([GlobalSecondaryIndex], False),\n        'KeySchema': ([KeySchema], True),\n        'LocalSecondaryIndexes': ([LocalSecondaryIndex], False),\n        'PointInTimeRecoverySpecification':\n            (PointInTimeRecoverySpecification, False),\n        'ProvisionedThroughput': (ProvisionedThroughput, False),\n        'SSESpecification': (SSESpecification, False),\n        'StreamSpecification': (StreamSpecification, False),\n        'TableName': (basestring, False),\n        'Tags': (Tags, False),\n        'TimeToLiveSpecification': (TimeToLiveSpecification, False),\n    }\n\n    def validate(self):\n        billing_mode = self.properties.get('BillingMode', 'PROVISIONED')\n        indexes = self.properties.get('GlobalSecondaryIndexes', [])\n        tput_props = [self.properties]\n        tput_props.extend([\n            x.properties for x in indexes if not isinstance(x, AWSHelperFn)\n        ])\n\n        def check_if_all(name, props):\n            validated = []\n            for prop in props:\n                is_helper = isinstance(prop.get(name), AWSHelperFn)\n                validated.append(name in prop or is_helper)\n            return all(validated)\n\n        def check_any(name, props):\n            validated = []\n            for prop in props:\n                is_helper = isinstance(prop.get(name), AWSHelperFn)\n                validated.append(name in prop and not is_helper)\n            return any(validated)\n\n        if isinstance(billing_mode, If):\n            if check_any('ProvisionedThroughput', tput_props):\n                raise ValueError(\n                    'Table billing mode is per-request. '\n                    'ProvisionedThroughput property is mutually exclusive')\n            return\n\n        if billing_mode == 'PROVISIONED':\n            if not check_if_all('ProvisionedThroughput', tput_props):\n                raise ValueError(\n                    'Table billing mode is provisioned. '\n                    'ProvisionedThroughput required if available')\n        elif billing_mode == 'PAY_PER_REQUEST':\n            if check_any('ProvisionedThroughput', tput_props):\n                raise ValueError(\n                    'Table billing mode is per-request. '\n                    'ProvisionedThroughput property is mutually exclusive')\n", "path": "troposphere/dynamodb.py"}]}