We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Python version support
I run the unit tests in a local environment, with Python 3.7.4

https://github.com/wangkuiyi/elasticdl/blob/424a9b45999fe77eb671d7cfe86d7e22130f263b/elasticdl/python/common/odps_recordio_conversion_utils.py#L52-L56

I find that it throws an exception. This is an interface change from Python 3.6 to Python 3.7
Please refer to https://docs.python.org/3/library/collections.html#collections.namedtuple

```
Changed in version 3.1: Added support for rename.

Changed in version 3.6: The verbose and rename parameters became keyword-only arguments.

Changed in version 3.6: Added the module parameter.

Changed in version 3.7: Remove the verbose parameter and the _source attribute.

Changed in version 3.7: Added the defaults parameter and the _field_defaults attribute.
```

Here is just a record.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `elasticdl/python/common/odps_recordio_conversion_utils.py`
Content:
```
1 import os
2 from collections import OrderedDict, namedtuple
3 from datetime import datetime as _datetime
4 
5 import numpy as np
6 import recordio
7 import tensorflow as tf
8 from odps.types import (
9     Bigint,
10     Binary,
11     Boolean,
12     Datetime,
13     Double,
14     Float,
15     Int,
16     Smallint,
17     String,
18     Tinyint,
19 )
20 
21 
22 def _infer_primitive_data_type(value):
23     """Infer the primitive data type for an ODPS value."""
24     integer_builtins = (int, np.integer)
25     float_builtins = (float, np.float)
26 
27     odps_primitive_to_builtin_types = OrderedDict(
28         (
29             (Bigint(), integer_builtins),
30             (Tinyint(), integer_builtins),
31             (Smallint(), integer_builtins),
32             (Int(), integer_builtins),
33             (Double(), float_builtins),
34             (Float(), float_builtins),
35             (String(), (str, bytes)),
36             (Binary(), bytes),
37             (Datetime(), _datetime),
38             (Boolean(), bool),
39         )
40     )
41     for data_type, builtin_types in odps_primitive_to_builtin_types.items():
42         if isinstance(value, builtin_types):
43             return builtin_types
44         else:
45             return None
46 
47 
48 def _find_features_indices(
49     features_list, int_features, float_features, bytes_features
50 ):
51     """Finds the indices for different types of features."""
52     FeatureIndices = namedtuple(
53         "FeatureIndices",
54         ["int_features", "float_features", "bytes_features"],
55         verbose=False,
56     )
57     int_features_indices = [features_list.index(key) for key in int_features]
58     float_features_indices = [
59         features_list.index(key) for key in float_features
60     ]
61     bytes_features_indices = [
62         features_list.index(key) for key in bytes_features
63     ]
64     return FeatureIndices(
65         int_features_indices, float_features_indices, bytes_features_indices
66     )
67 
68 
69 def _parse_row_to_example(record, features_list, feature_indices):
70     """
71     Parses one row (a flat list or one-dimensional numpy array)
72     to a TensorFlow Example.
73     """
74     if isinstance(record, list):
75         record = np.array(record, dtype=object)
76 
77     example = tf.train.Example()
78     # Note: these cannot be constructed dynamically since
79     # we cannot assign a value to an embedded message
80     # field in protobuf
81     for feature_ind in feature_indices.int_features:
82         example.features.feature[
83             features_list[feature_ind]
84         ].int64_list.value.append(
85             int(_maybe_encode_unicode_string(record[feature_ind]) or 0)
86         )
87     for feature_ind in feature_indices.float_features:
88         example.features.feature[
89             features_list[feature_ind]
90         ].float_list.value.append(
91             float(_maybe_encode_unicode_string(record[feature_ind]) or 0.0)
92         )
93     for feature_ind in feature_indices.bytes_features:
94         example.features.feature[
95             features_list[feature_ind]
96         ].bytes_list.value.append(
97             _maybe_encode_unicode_string(record[feature_ind])
98         )
99     return example
100 
101 
102 def _maybe_encode_unicode_string(record):
103     """Encodes unicode strings if needed."""
104     if isinstance(record, str):
105         record = bytes(record, "utf-8").strip()
106     return record
107 
108 
109 def _find_feature_indices_from_record(record):
110     """Find the indices of different feature types."""
111     feature_types = [type(value) for value in record]
112     FeatureIndices = namedtuple(
113         "FeatureIndices",
114         ["int_features", "float_features", "bytes_features"],
115         verbose=False,
116     )
117     return FeatureIndices(
118         [i for i, x in enumerate(feature_types) if x == int],
119         [i for i, x in enumerate(feature_types) if x == float],
120         [i for i, x in enumerate(feature_types) if x == str],
121     )
122 
123 
124 def write_recordio_shards_from_iterator(
125     records_iter, features_list, output_dir, records_per_shard
126 ):
127     """Writes RecordIO files from Python iterator of numpy arrays."""
128     # Take the first record batch to check whether it contains multiple items
129     first_record_batch = next(records_iter)
130     is_first_record_batch_consumed = False
131     is_multi_items_per_batch = any(
132         isinstance(i, list) for i in first_record_batch
133     )
134 
135     # Find the features of different types that will be used
136     # in `_parse_row_to_example()` later
137     record = (
138         first_record_batch[0]
139         if is_multi_items_per_batch
140         else first_record_batch
141     )
142     feature_indices = _find_feature_indices_from_record(record)
143 
144     writer = None
145     rows_written = 0
146     shards_written = 0
147     while True:
148         try:
149             # Make sure to consume the first record batch
150             if is_first_record_batch_consumed:
151                 record_batch = next(records_iter)
152             else:
153                 record_batch = first_record_batch
154                 is_first_record_batch_consumed = True
155             if not is_multi_items_per_batch:
156                 record_batch = [record_batch]
157 
158             # Write each record in the batch to a RecordIO shard
159             for record in record_batch:
160                 # Initialize the writer for the new shard
161                 if rows_written % records_per_shard == 0:
162                     if writer is not None:
163                         writer.close()
164                     shard_file_path = os.path.join(
165                         output_dir, "data-%05d" % shards_written
166                     )
167                     writer = recordio.Writer(shard_file_path)
168                     shards_written += 1
169 
170                 writer.write(
171                     _parse_row_to_example(
172                         record, features_list, feature_indices
173                     ).SerializeToString()
174                 )
175                 rows_written += 1
176         except StopIteration:
177             break
178 
179     writer.close()
180
```

Path: `setup.py`
Content:
```
1 from setuptools import setup, find_packages
2 
3 
4 with open('elasticdl/requirements.txt') as f:
5     requirements = f.read().splitlines()
6 
7 setup(
8     name="elasticdl",
9     version="0.0.1",
10     description="A Kubernetes-native Elastic Deep Learning Framework",
11     author="Ant Financial",
12     url="https://github.com/wangkuiyi/elasticdl",
13     install_requires=requirements,
14     packages=find_packages(exclude=["*test*"]),
15     package_data={"": ["proto/elasticdl.proto", "docker/*", "Makefile"]},
16     entry_points={
17         "console_scripts": ["elasticdl=elasticdl.python.elasticdl.client:main"]
18     },
19 )
20
```
--- 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/elasticdl/python/common/odps_recordio_conversion_utils.py b/elasticdl/python/common/odps_recordio_conversion_utils.py
--- a/elasticdl/python/common/odps_recordio_conversion_utils.py
+++ b/elasticdl/python/common/odps_recordio_conversion_utils.py
@@ -50,9 +50,7 @@
 ):
     """Finds the indices for different types of features."""
     FeatureIndices = namedtuple(
-        "FeatureIndices",
-        ["int_features", "float_features", "bytes_features"],
-        verbose=False,
+        "FeatureIndices", ["int_features", "float_features", "bytes_features"]
     )
     int_features_indices = [features_list.index(key) for key in int_features]
     float_features_indices = [
@@ -110,9 +108,7 @@
     """Find the indices of different feature types."""
     feature_types = [type(value) for value in record]
     FeatureIndices = namedtuple(
-        "FeatureIndices",
-        ["int_features", "float_features", "bytes_features"],
-        verbose=False,
+        "FeatureIndices", ["int_features", "float_features", "bytes_features"]
     )
     return FeatureIndices(
         [i for i, x in enumerate(feature_types) if x == int],
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -1,7 +1,6 @@
-from setuptools import setup, find_packages
+from setuptools import find_packages, setup
 
-
-with open('elasticdl/requirements.txt') as f:
+with open("elasticdl/requirements.txt") as f:
     requirements = f.read().splitlines()
 
 setup(

{"golden_diff": "diff --git a/elasticdl/python/common/odps_recordio_conversion_utils.py b/elasticdl/python/common/odps_recordio_conversion_utils.py\n--- a/elasticdl/python/common/odps_recordio_conversion_utils.py\n+++ b/elasticdl/python/common/odps_recordio_conversion_utils.py\n@@ -50,9 +50,7 @@\n ):\n     \"\"\"Finds the indices for different types of features.\"\"\"\n     FeatureIndices = namedtuple(\n-        \"FeatureIndices\",\n-        [\"int_features\", \"float_features\", \"bytes_features\"],\n-        verbose=False,\n+        \"FeatureIndices\", [\"int_features\", \"float_features\", \"bytes_features\"]\n     )\n     int_features_indices = [features_list.index(key) for key in int_features]\n     float_features_indices = [\n@@ -110,9 +108,7 @@\n     \"\"\"Find the indices of different feature types.\"\"\"\n     feature_types = [type(value) for value in record]\n     FeatureIndices = namedtuple(\n-        \"FeatureIndices\",\n-        [\"int_features\", \"float_features\", \"bytes_features\"],\n-        verbose=False,\n+        \"FeatureIndices\", [\"int_features\", \"float_features\", \"bytes_features\"]\n     )\n     return FeatureIndices(\n         [i for i, x in enumerate(feature_types) if x == int],\ndiff --git a/setup.py b/setup.py\n--- a/setup.py\n+++ b/setup.py\n@@ -1,7 +1,6 @@\n-from setuptools import setup, find_packages\n+from setuptools import find_packages, setup\n \n-\n-with open('elasticdl/requirements.txt') as f:\n+with open(\"elasticdl/requirements.txt\") as f:\n     requirements = f.read().splitlines()\n \n setup(\n", "issue": "Python version support\nI run the unit tests in a local environment, with Python 3.7.4\r\n\r\nhttps://github.com/wangkuiyi/elasticdl/blob/424a9b45999fe77eb671d7cfe86d7e22130f263b/elasticdl/python/common/odps_recordio_conversion_utils.py#L52-L56\r\n\r\nI find that it throws an exception. This is an interface change from Python 3.6 to Python 3.7\r\nPlease refer to https://docs.python.org/3/library/collections.html#collections.namedtuple\r\n\r\n```\r\nChanged in version 3.1: Added support for rename.\r\n\r\nChanged in version 3.6: The verbose and rename parameters became keyword-only arguments.\r\n\r\nChanged in version 3.6: Added the module parameter.\r\n\r\nChanged in version 3.7: Remove the verbose parameter and the _source attribute.\r\n\r\nChanged in version 3.7: Added the defaults parameter and the _field_defaults attribute.\r\n```\r\n\r\nHere is just a record.\n", "before_files": [{"content": "import os\nfrom collections import OrderedDict, namedtuple\nfrom datetime import datetime as _datetime\n\nimport numpy as np\nimport recordio\nimport tensorflow as tf\nfrom odps.types import (\n    Bigint,\n    Binary,\n    Boolean,\n    Datetime,\n    Double,\n    Float,\n    Int,\n    Smallint,\n    String,\n    Tinyint,\n)\n\n\ndef _infer_primitive_data_type(value):\n    \"\"\"Infer the primitive data type for an ODPS value.\"\"\"\n    integer_builtins = (int, np.integer)\n    float_builtins = (float, np.float)\n\n    odps_primitive_to_builtin_types = OrderedDict(\n        (\n            (Bigint(), integer_builtins),\n            (Tinyint(), integer_builtins),\n            (Smallint(), integer_builtins),\n            (Int(), integer_builtins),\n            (Double(), float_builtins),\n            (Float(), float_builtins),\n            (String(), (str, bytes)),\n            (Binary(), bytes),\n            (Datetime(), _datetime),\n            (Boolean(), bool),\n        )\n    )\n    for data_type, builtin_types in odps_primitive_to_builtin_types.items():\n        if isinstance(value, builtin_types):\n            return builtin_types\n        else:\n            return None\n\n\ndef _find_features_indices(\n    features_list, int_features, float_features, bytes_features\n):\n    \"\"\"Finds the indices for different types of features.\"\"\"\n    FeatureIndices = namedtuple(\n        \"FeatureIndices\",\n        [\"int_features\", \"float_features\", \"bytes_features\"],\n        verbose=False,\n    )\n    int_features_indices = [features_list.index(key) for key in int_features]\n    float_features_indices = [\n        features_list.index(key) for key in float_features\n    ]\n    bytes_features_indices = [\n        features_list.index(key) for key in bytes_features\n    ]\n    return FeatureIndices(\n        int_features_indices, float_features_indices, bytes_features_indices\n    )\n\n\ndef _parse_row_to_example(record, features_list, feature_indices):\n    \"\"\"\n    Parses one row (a flat list or one-dimensional numpy array)\n    to a TensorFlow Example.\n    \"\"\"\n    if isinstance(record, list):\n        record = np.array(record, dtype=object)\n\n    example = tf.train.Example()\n    # Note: these cannot be constructed dynamically since\n    # we cannot assign a value to an embedded message\n    # field in protobuf\n    for feature_ind in feature_indices.int_features:\n        example.features.feature[\n            features_list[feature_ind]\n        ].int64_list.value.append(\n            int(_maybe_encode_unicode_string(record[feature_ind]) or 0)\n        )\n    for feature_ind in feature_indices.float_features:\n        example.features.feature[\n            features_list[feature_ind]\n        ].float_list.value.append(\n            float(_maybe_encode_unicode_string(record[feature_ind]) or 0.0)\n        )\n    for feature_ind in feature_indices.bytes_features:\n        example.features.feature[\n            features_list[feature_ind]\n        ].bytes_list.value.append(\n            _maybe_encode_unicode_string(record[feature_ind])\n        )\n    return example\n\n\ndef _maybe_encode_unicode_string(record):\n    \"\"\"Encodes unicode strings if needed.\"\"\"\n    if isinstance(record, str):\n        record = bytes(record, \"utf-8\").strip()\n    return record\n\n\ndef _find_feature_indices_from_record(record):\n    \"\"\"Find the indices of different feature types.\"\"\"\n    feature_types = [type(value) for value in record]\n    FeatureIndices = namedtuple(\n        \"FeatureIndices\",\n        [\"int_features\", \"float_features\", \"bytes_features\"],\n        verbose=False,\n    )\n    return FeatureIndices(\n        [i for i, x in enumerate(feature_types) if x == int],\n        [i for i, x in enumerate(feature_types) if x == float],\n        [i for i, x in enumerate(feature_types) if x == str],\n    )\n\n\ndef write_recordio_shards_from_iterator(\n    records_iter, features_list, output_dir, records_per_shard\n):\n    \"\"\"Writes RecordIO files from Python iterator of numpy arrays.\"\"\"\n    # Take the first record batch to check whether it contains multiple items\n    first_record_batch = next(records_iter)\n    is_first_record_batch_consumed = False\n    is_multi_items_per_batch = any(\n        isinstance(i, list) for i in first_record_batch\n    )\n\n    # Find the features of different types that will be used\n    # in `_parse_row_to_example()` later\n    record = (\n        first_record_batch[0]\n        if is_multi_items_per_batch\n        else first_record_batch\n    )\n    feature_indices = _find_feature_indices_from_record(record)\n\n    writer = None\n    rows_written = 0\n    shards_written = 0\n    while True:\n        try:\n            # Make sure to consume the first record batch\n            if is_first_record_batch_consumed:\n                record_batch = next(records_iter)\n            else:\n                record_batch = first_record_batch\n                is_first_record_batch_consumed = True\n            if not is_multi_items_per_batch:\n                record_batch = [record_batch]\n\n            # Write each record in the batch to a RecordIO shard\n            for record in record_batch:\n                # Initialize the writer for the new shard\n                if rows_written % records_per_shard == 0:\n                    if writer is not None:\n                        writer.close()\n                    shard_file_path = os.path.join(\n                        output_dir, \"data-%05d\" % shards_written\n                    )\n                    writer = recordio.Writer(shard_file_path)\n                    shards_written += 1\n\n                writer.write(\n                    _parse_row_to_example(\n                        record, features_list, feature_indices\n                    ).SerializeToString()\n                )\n                rows_written += 1\n        except StopIteration:\n            break\n\n    writer.close()\n", "path": "elasticdl/python/common/odps_recordio_conversion_utils.py"}, {"content": "from setuptools import setup, find_packages\n\n\nwith open('elasticdl/requirements.txt') as f:\n    requirements = f.read().splitlines()\n\nsetup(\n    name=\"elasticdl\",\n    version=\"0.0.1\",\n    description=\"A Kubernetes-native Elastic Deep Learning Framework\",\n    author=\"Ant Financial\",\n    url=\"https://github.com/wangkuiyi/elasticdl\",\n    install_requires=requirements,\n    packages=find_packages(exclude=[\"*test*\"]),\n    package_data={\"\": [\"proto/elasticdl.proto\", \"docker/*\", \"Makefile\"]},\n    entry_points={\n        \"console_scripts\": [\"elasticdl=elasticdl.python.elasticdl.client:main\"]\n    },\n)\n", "path": "setup.py"}], "after_files": [{"content": "import os\nfrom collections import OrderedDict, namedtuple\nfrom datetime import datetime as _datetime\n\nimport numpy as np\nimport recordio\nimport tensorflow as tf\nfrom odps.types import (\n    Bigint,\n    Binary,\n    Boolean,\n    Datetime,\n    Double,\n    Float,\n    Int,\n    Smallint,\n    String,\n    Tinyint,\n)\n\n\ndef _infer_primitive_data_type(value):\n    \"\"\"Infer the primitive data type for an ODPS value.\"\"\"\n    integer_builtins = (int, np.integer)\n    float_builtins = (float, np.float)\n\n    odps_primitive_to_builtin_types = OrderedDict(\n        (\n            (Bigint(), integer_builtins),\n            (Tinyint(), integer_builtins),\n            (Smallint(), integer_builtins),\n            (Int(), integer_builtins),\n            (Double(), float_builtins),\n            (Float(), float_builtins),\n            (String(), (str, bytes)),\n            (Binary(), bytes),\n            (Datetime(), _datetime),\n            (Boolean(), bool),\n        )\n    )\n    for data_type, builtin_types in odps_primitive_to_builtin_types.items():\n        if isinstance(value, builtin_types):\n            return builtin_types\n        else:\n            return None\n\n\ndef _find_features_indices(\n    features_list, int_features, float_features, bytes_features\n):\n    \"\"\"Finds the indices for different types of features.\"\"\"\n    FeatureIndices = namedtuple(\n        \"FeatureIndices\", [\"int_features\", \"float_features\", \"bytes_features\"]\n    )\n    int_features_indices = [features_list.index(key) for key in int_features]\n    float_features_indices = [\n        features_list.index(key) for key in float_features\n    ]\n    bytes_features_indices = [\n        features_list.index(key) for key in bytes_features\n    ]\n    return FeatureIndices(\n        int_features_indices, float_features_indices, bytes_features_indices\n    )\n\n\ndef _parse_row_to_example(record, features_list, feature_indices):\n    \"\"\"\n    Parses one row (a flat list or one-dimensional numpy array)\n    to a TensorFlow Example.\n    \"\"\"\n    if isinstance(record, list):\n        record = np.array(record, dtype=object)\n\n    example = tf.train.Example()\n    # Note: these cannot be constructed dynamically since\n    # we cannot assign a value to an embedded message\n    # field in protobuf\n    for feature_ind in feature_indices.int_features:\n        example.features.feature[\n            features_list[feature_ind]\n        ].int64_list.value.append(\n            int(_maybe_encode_unicode_string(record[feature_ind]) or 0)\n        )\n    for feature_ind in feature_indices.float_features:\n        example.features.feature[\n            features_list[feature_ind]\n        ].float_list.value.append(\n            float(_maybe_encode_unicode_string(record[feature_ind]) or 0.0)\n        )\n    for feature_ind in feature_indices.bytes_features:\n        example.features.feature[\n            features_list[feature_ind]\n        ].bytes_list.value.append(\n            _maybe_encode_unicode_string(record[feature_ind])\n        )\n    return example\n\n\ndef _maybe_encode_unicode_string(record):\n    \"\"\"Encodes unicode strings if needed.\"\"\"\n    if isinstance(record, str):\n        record = bytes(record, \"utf-8\").strip()\n    return record\n\n\ndef _find_feature_indices_from_record(record):\n    \"\"\"Find the indices of different feature types.\"\"\"\n    feature_types = [type(value) for value in record]\n    FeatureIndices = namedtuple(\n        \"FeatureIndices\", [\"int_features\", \"float_features\", \"bytes_features\"]\n    )\n    return FeatureIndices(\n        [i for i, x in enumerate(feature_types) if x == int],\n        [i for i, x in enumerate(feature_types) if x == float],\n        [i for i, x in enumerate(feature_types) if x == str],\n    )\n\n\ndef write_recordio_shards_from_iterator(\n    records_iter, features_list, output_dir, records_per_shard\n):\n    \"\"\"Writes RecordIO files from Python iterator of numpy arrays.\"\"\"\n    # Take the first record batch to check whether it contains multiple items\n    first_record_batch = next(records_iter)\n    is_first_record_batch_consumed = False\n    is_multi_items_per_batch = any(\n        isinstance(i, list) for i in first_record_batch\n    )\n\n    # Find the features of different types that will be used\n    # in `_parse_row_to_example()` later\n    record = (\n        first_record_batch[0]\n        if is_multi_items_per_batch\n        else first_record_batch\n    )\n    feature_indices = _find_feature_indices_from_record(record)\n\n    writer = None\n    rows_written = 0\n    shards_written = 0\n    while True:\n        try:\n            # Make sure to consume the first record batch\n            if is_first_record_batch_consumed:\n                record_batch = next(records_iter)\n            else:\n                record_batch = first_record_batch\n                is_first_record_batch_consumed = True\n            if not is_multi_items_per_batch:\n                record_batch = [record_batch]\n\n            # Write each record in the batch to a RecordIO shard\n            for record in record_batch:\n                # Initialize the writer for the new shard\n                if rows_written % records_per_shard == 0:\n                    if writer is not None:\n                        writer.close()\n                    shard_file_path = os.path.join(\n                        output_dir, \"data-%05d\" % shards_written\n                    )\n                    writer = recordio.Writer(shard_file_path)\n                    shards_written += 1\n\n                writer.write(\n                    _parse_row_to_example(\n                        record, features_list, feature_indices\n                    ).SerializeToString()\n                )\n                rows_written += 1\n        except StopIteration:\n            break\n\n    writer.close()\n", "path": "elasticdl/python/common/odps_recordio_conversion_utils.py"}, {"content": "from setuptools import find_packages, setup\n\nwith open(\"elasticdl/requirements.txt\") as f:\n    requirements = f.read().splitlines()\n\nsetup(\n    name=\"elasticdl\",\n    version=\"0.0.1\",\n    description=\"A Kubernetes-native Elastic Deep Learning Framework\",\n    author=\"Ant Financial\",\n    url=\"https://github.com/wangkuiyi/elasticdl\",\n    install_requires=requirements,\n    packages=find_packages(exclude=[\"*test*\"]),\n    package_data={\"\": [\"proto/elasticdl.proto\", \"docker/*\", \"Makefile\"]},\n    entry_points={\n        \"console_scripts\": [\"elasticdl=elasticdl.python.elasticdl.client:main\"]\n    },\n)\n", "path": "setup.py"}]}