We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Extract meta failure on missing props docstring.
If a props is missing a docstring, it will fail to generate the component with js error, `Cannot read property 'length' of undefined`.

https://community.plot.ly/t/dash-component-creation-javascript-ok-nothing-rendered-in-python/19369

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `dash/development/component_generator.py`
Content:
```
1 from __future__ import print_function
2 from collections import OrderedDict
3 
4 import json
5 import sys
6 import subprocess
7 import shlex
8 import os
9 import argparse
10 import shutil
11 import functools
12 
13 import pkg_resources
14 
15 from ._r_components_generation import write_class_file
16 from ._r_components_generation import generate_exports
17 from ._py_components_generation import generate_class_file
18 from ._py_components_generation import generate_imports
19 from ._py_components_generation import generate_classes_files
20 
21 
22 class _CombinedFormatter(argparse.ArgumentDefaultsHelpFormatter,
23                          argparse.RawDescriptionHelpFormatter):
24     pass
25 
26 
27 # pylint: disable=too-many-locals
28 def generate_components(components_source, project_shortname,
29                         package_info_filename='package.json',
30                         ignore='^_',
31                         rprefix=None):
32 
33     project_shortname = project_shortname.replace('-', '_').rstrip('/\\')
34 
35     if rprefix:
36         prefix = rprefix
37 
38     is_windows = sys.platform == 'win32'
39 
40     extract_path = pkg_resources.resource_filename('dash', 'extract-meta.js')
41 
42     os.environ['NODE_PATH'] = 'node_modules'
43     cmd = shlex.split(
44         'node {} {} {}'.format(extract_path, ignore, components_source),
45         posix=not is_windows
46     )
47 
48     shutil.copyfile('package.json',
49                     os.path.join(project_shortname, package_info_filename))
50 
51     proc = subprocess.Popen(cmd,
52                             stdout=subprocess.PIPE,
53                             stderr=subprocess.PIPE,
54                             shell=is_windows)
55     out, err = proc.communicate()
56     status = proc.poll()
57 
58     if err:
59         print(err.decode(), file=sys.stderr)
60 
61     if not out:
62         print(
63             'Error generating metadata in {} (status={})'.format(
64                 project_shortname, status),
65             file=sys.stderr)
66         sys.exit(1)
67 
68     jsondata_unicode = json.loads(out.decode(), object_pairs_hook=OrderedDict)
69 
70     if sys.version_info[0] >= 3:
71         metadata = jsondata_unicode
72     else:
73         metadata = byteify(jsondata_unicode)
74 
75     generator_methods = [generate_class_file]
76 
77     if rprefix:
78         if not os.path.exists('man'):
79             os.makedirs('man')
80         if not os.path.exists('R'):
81             os.makedirs('R')
82         generator_methods.append(
83             functools.partial(write_class_file, prefix=prefix))
84 
85     components = generate_classes_files(
86         project_shortname,
87         metadata,
88         *generator_methods
89     )
90 
91     with open(os.path.join(project_shortname, 'metadata.json'), 'w') as f:
92         json.dump(metadata, f)
93 
94     generate_imports(project_shortname, components)
95 
96     if rprefix:
97         with open('package.json', 'r') as f:
98             jsondata_unicode = json.load(f, object_pairs_hook=OrderedDict)
99             if sys.version_info[0] >= 3:
100                 pkg_data = jsondata_unicode
101             else:
102                 pkg_data = byteify(jsondata_unicode)
103 
104         generate_exports(
105             project_shortname, components, metadata, pkg_data, prefix
106         )
107 
108 
109 def cli():
110     parser = argparse.ArgumentParser(
111         prog='dash-generate-components',
112         formatter_class=_CombinedFormatter,
113         description='Generate dash components by extracting the metadata '
114         'using react-docgen. Then map the metadata to python classes.'
115     )
116     parser.add_argument('components_source',
117                         help='React components source directory.')
118     parser.add_argument(
119         'project_shortname',
120         help='Name of the project to export the classes files.'
121     )
122     parser.add_argument(
123         '-p', '--package-info-filename',
124         default='package.json',
125         help='The filename of the copied `package.json` to `project_shortname`'
126     )
127     parser.add_argument(
128         '-i', '--ignore',
129         default='^_',
130         help='Files/directories matching the pattern will be ignored'
131     )
132     parser.add_argument(
133         '--r-prefix',
134         help='Experimental: specify a prefix for DashR component names, write'
135              'DashR components to R dir, create R package.'
136     )
137 
138     args = parser.parse_args()
139     generate_components(
140         args.components_source, args.project_shortname,
141         package_info_filename=args.package_info_filename,
142         ignore=args.ignore,
143         rprefix=args.r_prefix)
144 
145 
146 # pylint: disable=undefined-variable
147 def byteify(input_object):
148     if isinstance(input_object, dict):
149         return OrderedDict([
150             (byteify(key), byteify(value))
151             for key, value in input_object.iteritems()
152         ])
153     elif isinstance(input_object, list):
154         return [byteify(element) for element in input_object]
155     elif isinstance(input_object, unicode):  # noqa:F821
156         return input_object.encode('utf-8')
157     return input_object
158 
159 
160 if __name__ == '__main__':
161     cli()
162
```
--- 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/dash/development/component_generator.py b/dash/development/component_generator.py
--- a/dash/development/component_generator.py
+++ b/dash/development/component_generator.py
@@ -89,7 +89,7 @@
     )
 
     with open(os.path.join(project_shortname, 'metadata.json'), 'w') as f:
-        json.dump(metadata, f)
+        json.dump(metadata, f, indent=2)
 
     generate_imports(project_shortname, components)

{"golden_diff": "diff --git a/dash/development/component_generator.py b/dash/development/component_generator.py\n--- a/dash/development/component_generator.py\n+++ b/dash/development/component_generator.py\n@@ -89,7 +89,7 @@\n     )\n \n     with open(os.path.join(project_shortname, 'metadata.json'), 'w') as f:\n-        json.dump(metadata, f)\n+        json.dump(metadata, f, indent=2)\n \n     generate_imports(project_shortname, components)\n", "issue": "Extract meta failure on missing props docstring.\nIf a props is missing a docstring, it will fail to generate the component with js error, `Cannot read property 'length' of undefined`.\r\n\r\nhttps://community.plot.ly/t/dash-component-creation-javascript-ok-nothing-rendered-in-python/19369\n", "before_files": [{"content": "from __future__ import print_function\nfrom collections import OrderedDict\n\nimport json\nimport sys\nimport subprocess\nimport shlex\nimport os\nimport argparse\nimport shutil\nimport functools\n\nimport pkg_resources\n\nfrom ._r_components_generation import write_class_file\nfrom ._r_components_generation import generate_exports\nfrom ._py_components_generation import generate_class_file\nfrom ._py_components_generation import generate_imports\nfrom ._py_components_generation import generate_classes_files\n\n\nclass _CombinedFormatter(argparse.ArgumentDefaultsHelpFormatter,\n                         argparse.RawDescriptionHelpFormatter):\n    pass\n\n\n# pylint: disable=too-many-locals\ndef generate_components(components_source, project_shortname,\n                        package_info_filename='package.json',\n                        ignore='^_',\n                        rprefix=None):\n\n    project_shortname = project_shortname.replace('-', '_').rstrip('/\\\\')\n\n    if rprefix:\n        prefix = rprefix\n\n    is_windows = sys.platform == 'win32'\n\n    extract_path = pkg_resources.resource_filename('dash', 'extract-meta.js')\n\n    os.environ['NODE_PATH'] = 'node_modules'\n    cmd = shlex.split(\n        'node {} {} {}'.format(extract_path, ignore, components_source),\n        posix=not is_windows\n    )\n\n    shutil.copyfile('package.json',\n                    os.path.join(project_shortname, package_info_filename))\n\n    proc = subprocess.Popen(cmd,\n                            stdout=subprocess.PIPE,\n                            stderr=subprocess.PIPE,\n                            shell=is_windows)\n    out, err = proc.communicate()\n    status = proc.poll()\n\n    if err:\n        print(err.decode(), file=sys.stderr)\n\n    if not out:\n        print(\n            'Error generating metadata in {} (status={})'.format(\n                project_shortname, status),\n            file=sys.stderr)\n        sys.exit(1)\n\n    jsondata_unicode = json.loads(out.decode(), object_pairs_hook=OrderedDict)\n\n    if sys.version_info[0] >= 3:\n        metadata = jsondata_unicode\n    else:\n        metadata = byteify(jsondata_unicode)\n\n    generator_methods = [generate_class_file]\n\n    if rprefix:\n        if not os.path.exists('man'):\n            os.makedirs('man')\n        if not os.path.exists('R'):\n            os.makedirs('R')\n        generator_methods.append(\n            functools.partial(write_class_file, prefix=prefix))\n\n    components = generate_classes_files(\n        project_shortname,\n        metadata,\n        *generator_methods\n    )\n\n    with open(os.path.join(project_shortname, 'metadata.json'), 'w') as f:\n        json.dump(metadata, f)\n\n    generate_imports(project_shortname, components)\n\n    if rprefix:\n        with open('package.json', 'r') as f:\n            jsondata_unicode = json.load(f, object_pairs_hook=OrderedDict)\n            if sys.version_info[0] >= 3:\n                pkg_data = jsondata_unicode\n            else:\n                pkg_data = byteify(jsondata_unicode)\n\n        generate_exports(\n            project_shortname, components, metadata, pkg_data, prefix\n        )\n\n\ndef cli():\n    parser = argparse.ArgumentParser(\n        prog='dash-generate-components',\n        formatter_class=_CombinedFormatter,\n        description='Generate dash components by extracting the metadata '\n        'using react-docgen. Then map the metadata to python classes.'\n    )\n    parser.add_argument('components_source',\n                        help='React components source directory.')\n    parser.add_argument(\n        'project_shortname',\n        help='Name of the project to export the classes files.'\n    )\n    parser.add_argument(\n        '-p', '--package-info-filename',\n        default='package.json',\n        help='The filename of the copied `package.json` to `project_shortname`'\n    )\n    parser.add_argument(\n        '-i', '--ignore',\n        default='^_',\n        help='Files/directories matching the pattern will be ignored'\n    )\n    parser.add_argument(\n        '--r-prefix',\n        help='Experimental: specify a prefix for DashR component names, write'\n             'DashR components to R dir, create R package.'\n    )\n\n    args = parser.parse_args()\n    generate_components(\n        args.components_source, args.project_shortname,\n        package_info_filename=args.package_info_filename,\n        ignore=args.ignore,\n        rprefix=args.r_prefix)\n\n\n# pylint: disable=undefined-variable\ndef byteify(input_object):\n    if isinstance(input_object, dict):\n        return OrderedDict([\n            (byteify(key), byteify(value))\n            for key, value in input_object.iteritems()\n        ])\n    elif isinstance(input_object, list):\n        return [byteify(element) for element in input_object]\n    elif isinstance(input_object, unicode):  # noqa:F821\n        return input_object.encode('utf-8')\n    return input_object\n\n\nif __name__ == '__main__':\n    cli()\n", "path": "dash/development/component_generator.py"}], "after_files": [{"content": "from __future__ import print_function\nfrom collections import OrderedDict\n\nimport json\nimport sys\nimport subprocess\nimport shlex\nimport os\nimport argparse\nimport shutil\nimport functools\n\nimport pkg_resources\n\nfrom ._r_components_generation import write_class_file\nfrom ._r_components_generation import generate_exports\nfrom ._py_components_generation import generate_class_file\nfrom ._py_components_generation import generate_imports\nfrom ._py_components_generation import generate_classes_files\n\n\nclass _CombinedFormatter(argparse.ArgumentDefaultsHelpFormatter,\n                         argparse.RawDescriptionHelpFormatter):\n    pass\n\n\n# pylint: disable=too-many-locals\ndef generate_components(components_source, project_shortname,\n                        package_info_filename='package.json',\n                        ignore='^_',\n                        rprefix=None):\n\n    project_shortname = project_shortname.replace('-', '_').rstrip('/\\\\')\n\n    if rprefix:\n        prefix = rprefix\n\n    is_windows = sys.platform == 'win32'\n\n    extract_path = pkg_resources.resource_filename('dash', 'extract-meta.js')\n\n    os.environ['NODE_PATH'] = 'node_modules'\n    cmd = shlex.split(\n        'node {} {} {}'.format(extract_path, ignore, components_source),\n        posix=not is_windows\n    )\n\n    shutil.copyfile('package.json',\n                    os.path.join(project_shortname, package_info_filename))\n\n    proc = subprocess.Popen(cmd,\n                            stdout=subprocess.PIPE,\n                            stderr=subprocess.PIPE,\n                            shell=is_windows)\n    out, err = proc.communicate()\n    status = proc.poll()\n\n    if err:\n        print(err.decode(), file=sys.stderr)\n\n    if not out:\n        print(\n            'Error generating metadata in {} (status={})'.format(\n                project_shortname, status),\n            file=sys.stderr)\n        sys.exit(1)\n\n    jsondata_unicode = json.loads(out.decode(), object_pairs_hook=OrderedDict)\n\n    if sys.version_info[0] >= 3:\n        metadata = jsondata_unicode\n    else:\n        metadata = byteify(jsondata_unicode)\n\n    generator_methods = [generate_class_file]\n\n    if rprefix:\n        if not os.path.exists('man'):\n            os.makedirs('man')\n        if not os.path.exists('R'):\n            os.makedirs('R')\n        generator_methods.append(\n            functools.partial(write_class_file, prefix=prefix))\n\n    components = generate_classes_files(\n        project_shortname,\n        metadata,\n        *generator_methods\n    )\n\n    with open(os.path.join(project_shortname, 'metadata.json'), 'w') as f:\n        json.dump(metadata, f, indent=2)\n\n    generate_imports(project_shortname, components)\n\n    if rprefix:\n        with open('package.json', 'r') as f:\n            jsondata_unicode = json.load(f, object_pairs_hook=OrderedDict)\n            if sys.version_info[0] >= 3:\n                pkg_data = jsondata_unicode\n            else:\n                pkg_data = byteify(jsondata_unicode)\n\n        generate_exports(\n            project_shortname, components, metadata, pkg_data, prefix\n        )\n\n\ndef cli():\n    parser = argparse.ArgumentParser(\n        prog='dash-generate-components',\n        formatter_class=_CombinedFormatter,\n        description='Generate dash components by extracting the metadata '\n        'using react-docgen. Then map the metadata to python classes.'\n    )\n    parser.add_argument('components_source',\n                        help='React components source directory.')\n    parser.add_argument(\n        'project_shortname',\n        help='Name of the project to export the classes files.'\n    )\n    parser.add_argument(\n        '-p', '--package-info-filename',\n        default='package.json',\n        help='The filename of the copied `package.json` to `project_shortname`'\n    )\n    parser.add_argument(\n        '-i', '--ignore',\n        default='^_',\n        help='Files/directories matching the pattern will be ignored'\n    )\n    parser.add_argument(\n        '--r-prefix',\n        help='Experimental: specify a prefix for DashR component names, write'\n             'DashR components to R dir, create R package.'\n    )\n\n    args = parser.parse_args()\n    generate_components(\n        args.components_source, args.project_shortname,\n        package_info_filename=args.package_info_filename,\n        ignore=args.ignore,\n        rprefix=args.r_prefix)\n\n\n# pylint: disable=undefined-variable\ndef byteify(input_object):\n    if isinstance(input_object, dict):\n        return OrderedDict([\n            (byteify(key), byteify(value))\n            for key, value in input_object.iteritems()\n        ])\n    elif isinstance(input_object, list):\n        return [byteify(element) for element in input_object]\n    elif isinstance(input_object, unicode):  # noqa:F821\n        return input_object.encode('utf-8')\n    return input_object\n\n\nif __name__ == '__main__':\n    cli()\n", "path": "dash/development/component_generator.py"}]}