We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
使用yolov3_mobilenet_v1_voc.yml训练时出错
Traceback (most recent call last):
  File "tools/train.py", line 372, in <module>
    main()
  File "tools/train.py", line 70, in main
    cfg = load_config(FLAGS.config)
  File "/home/aistudio/PaddleDetection/ppdet/core/workspace.py", line 86, in load_config
    cfg = merge_config(yaml.load(f, Loader=yaml.Loader), cfg)
  File "/home/aistudio/PaddleDetection/ppdet/core/workspace.py", line 143, in merge_config
    dct['train_batch_size'] = dct['TrainReader']['batch_size']
KeyError: 'batch_size'

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `ppdet/core/workspace.py`
Content:
```
1 # Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 
15 from __future__ import absolute_import
16 from __future__ import print_function
17 from __future__ import division
18 
19 import importlib
20 import os
21 import sys
22 
23 import yaml
24 import copy
25 import collections
26 
27 from .config.schema import SchemaDict, SharedConfig, extract_schema
28 from .config.yaml_helpers import serializable
29 
30 __all__ = [
31     'global_config',
32     'load_config',
33     'merge_config',
34     'get_registered_modules',
35     'create',
36     'register',
37     'serializable',
38     'dump_value',
39 ]
40 
41 
42 def dump_value(value):
43     # XXX this is hackish, but collections.abc is not available in python 2
44     if hasattr(value, '__dict__') or isinstance(value, (dict, tuple, list)):
45         value = yaml.dump(value, default_flow_style=True)
46         value = value.replace('\n', '')
47         value = value.replace('...', '')
48         return "'{}'".format(value)
49     else:
50         # primitive types
51         return str(value)
52 
53 
54 class AttrDict(dict):
55     """Single level attribute dict, NOT recursive"""
56 
57     def __init__(self, **kwargs):
58         super(AttrDict, self).__init__()
59         super(AttrDict, self).update(kwargs)
60 
61     def __getattr__(self, key):
62         if key in self:
63             return self[key]
64         raise AttributeError("object has no attribute '{}'".format(key))
65 
66 
67 global_config = AttrDict()
68 
69 READER_KEY = '_READER_'
70 
71 
72 def load_config(file_path):
73     """
74     Load config from file.
75 
76     Args:
77         file_path (str): Path of the config file to be loaded.
78 
79     Returns: global config
80     """
81     _, ext = os.path.splitext(file_path)
82     assert ext in ['.yml', '.yaml'], "only support yaml files for now"
83 
84     cfg = AttrDict()
85     with open(file_path) as f:
86         cfg = merge_config(yaml.load(f, Loader=yaml.Loader), cfg)
87 
88     if READER_KEY in cfg:
89         reader_cfg = cfg[READER_KEY]
90         if reader_cfg.startswith("~"):
91             reader_cfg = os.path.expanduser(reader_cfg)
92         if not reader_cfg.startswith('/'):
93             reader_cfg = os.path.join(os.path.dirname(file_path), reader_cfg)
94 
95         with open(reader_cfg) as f:
96             merge_config(yaml.load(f, Loader=yaml.Loader))
97         del cfg[READER_KEY]
98 
99     merge_config(cfg)
100 
101     return global_config
102 
103 
104 def dict_merge(dct, merge_dct):
105     """ Recursive dict merge. Inspired by :meth:``dict.update()``, instead of
106     updating only top-level keys, dict_merge recurses down into dicts nested
107     to an arbitrary depth, updating keys. The ``merge_dct`` is merged into
108     ``dct``.
109 
110     Args:
111         dct: dict onto which the merge is executed
112         merge_dct: dct merged into dct
113 
114     Returns: dct
115     """
116     for k, v in merge_dct.items():
117         if (k in dct and isinstance(dct[k], dict) and
118                 isinstance(merge_dct[k], collections.Mapping)):
119             dict_merge(dct[k], merge_dct[k])
120         else:
121             dct[k] = merge_dct[k]
122     return dct
123 
124 
125 def merge_config(config, another_cfg=None):
126     """
127     Merge config into global config or another_cfg.
128 
129     Args:
130         config (dict): Config to be merged.
131 
132     Returns: global config
133     """
134     global global_config
135     dct = another_cfg if another_cfg is not None else global_config
136     dct = dict_merge(dct, config)
137 
138     # NOTE: training batch size defined only in TrainReader, sychornized
139     #       batch size config to global, models can get batch size config
140     #       from global config when building model.
141     #       batch size in evaluation or inference can also be added here
142     if 'TrainReader' in dct:
143         dct['train_batch_size'] = dct['TrainReader']['batch_size']
144 
145     return dct
146 
147 
148 def get_registered_modules():
149     return {k: v for k, v in global_config.items() if isinstance(v, SchemaDict)}
150 
151 
152 def make_partial(cls):
153     if isinstance(cls.__op__, str):
154         sep = cls.__op__.split('.')
155         op_name = sep[-1]
156         op_module = importlib.import_module('.'.join(sep[:-1]))
157     else:
158         op_name = cls.__op__.__name__
159         op_module = importlib.import_module(cls.__op__.__module__)
160 
161     if not hasattr(op_module, op_name):
162         import logging
163         logger = logging.getLogger(__name__)
164         logger.warn('{} OP not found, maybe a newer version of paddle '
165                     'is required.'.format(cls.__op__))
166         return cls
167 
168     op = getattr(op_module, op_name)
169     cls.__category__ = getattr(cls, '__category__', None) or 'op'
170 
171     def partial_apply(self, *args, **kwargs):
172         kwargs_ = self.__dict__.copy()
173         kwargs_.update(kwargs)
174         return op(*args, **kwargs_)
175 
176     if getattr(cls, '__append_doc__', True):  # XXX should default to True?
177         if sys.version_info[0] > 2:
178             cls.__doc__ = "Wrapper for `{}` OP".format(op.__name__)
179             cls.__init__.__doc__ = op.__doc__
180             cls.__call__ = partial_apply
181             cls.__call__.__doc__ = op.__doc__
182         else:
183             # XXX work around for python 2
184             partial_apply.__doc__ = op.__doc__
185             cls.__call__ = partial_apply
186     return cls
187 
188 
189 def register(cls):
190     """
191     Register a given module class.
192 
193     Args:
194         cls (type): Module class to be registered.
195 
196     Returns: cls
197     """
198     if cls.__name__ in global_config:
199         raise ValueError("Module class already registered: {}".format(
200             cls.__name__))
201     if hasattr(cls, '__op__'):
202         cls = make_partial(cls)
203     global_config[cls.__name__] = extract_schema(cls)
204     return cls
205 
206 
207 def create(cls_or_name, **kwargs):
208     """
209     Create an instance of given module class.
210 
211     Args:
212         cls_or_name (type or str): Class of which to create instance.
213 
214     Returns: instance of type `cls_or_name`
215     """
216     assert type(cls_or_name) in [type, str
217                                  ], "should be a class or name of a class"
218     name = type(cls_or_name) == str and cls_or_name or cls_or_name.__name__
219     assert name in global_config and \
220         isinstance(global_config[name], SchemaDict), \
221         "the module {} is not registered".format(name)
222     config = global_config[name]
223     config.update(kwargs)
224     config.validate()
225     cls = getattr(config.pymodule, name)
226 
227     kwargs = {}
228     kwargs.update(global_config[name])
229 
230     # parse `shared` annoation of registered modules
231     if getattr(config, 'shared', None):
232         for k in config.shared:
233             target_key = config[k]
234             shared_conf = config.schema[k].default
235             assert isinstance(shared_conf, SharedConfig)
236             if target_key is not None and not isinstance(target_key,
237                                                          SharedConfig):
238                 continue  # value is given for the module
239             elif shared_conf.key in global_config:
240                 # `key` is present in config
241                 kwargs[k] = global_config[shared_conf.key]
242             else:
243                 kwargs[k] = shared_conf.default_value
244 
245     # parse `inject` annoation of registered modules
246     if getattr(config, 'inject', None):
247         for k in config.inject:
248             target_key = config[k]
249             # optional dependency
250             if target_key is None:
251                 continue
252             # also accept dictionaries and serialized objects
253             if isinstance(target_key, dict) or hasattr(target_key, '__dict__'):
254                 continue
255             elif isinstance(target_key, str):
256                 if target_key not in global_config:
257                     raise ValueError("Missing injection config:", target_key)
258                 target = global_config[target_key]
259                 if isinstance(target, SchemaDict):
260                     kwargs[k] = create(target_key)
261                 elif hasattr(target, '__dict__'):  # serialized object
262                     kwargs[k] = target
263             else:
264                 raise ValueError("Unsupported injection type:", target_key)
265     # prevent modification of global config values of reference types
266     # (e.g., list, dict) from within the created module instances
267     kwargs = copy.deepcopy(kwargs)
268     return cls(**kwargs)
269
```
--- 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/ppdet/core/workspace.py b/ppdet/core/workspace.py
--- a/ppdet/core/workspace.py
+++ b/ppdet/core/workspace.py
@@ -139,7 +139,7 @@
     #       batch size config to global, models can get batch size config
     #       from global config when building model.
     #       batch size in evaluation or inference can also be added here
-    if 'TrainReader' in dct:
+    if 'TrainReader' in dct and 'batch_size' in dct['TrainReader']:
         dct['train_batch_size'] = dct['TrainReader']['batch_size']
 
     return dct

{"golden_diff": "diff --git a/ppdet/core/workspace.py b/ppdet/core/workspace.py\n--- a/ppdet/core/workspace.py\n+++ b/ppdet/core/workspace.py\n@@ -139,7 +139,7 @@\n     #       batch size config to global, models can get batch size config\n     #       from global config when building model.\n     #       batch size in evaluation or inference can also be added here\n-    if 'TrainReader' in dct:\n+    if 'TrainReader' in dct and 'batch_size' in dct['TrainReader']:\n         dct['train_batch_size'] = dct['TrainReader']['batch_size']\n \n     return dct\n", "issue": "\u4f7f\u7528yolov3_mobilenet_v1_voc.yml\u8bad\u7ec3\u65f6\u51fa\u9519\nTraceback (most recent call last):\r\n  File \"tools/train.py\", line 372, in <module>\r\n    main()\r\n  File \"tools/train.py\", line 70, in main\r\n    cfg = load_config(FLAGS.config)\r\n  File \"/home/aistudio/PaddleDetection/ppdet/core/workspace.py\", line 86, in load_config\r\n    cfg = merge_config(yaml.load(f, Loader=yaml.Loader), cfg)\r\n  File \"/home/aistudio/PaddleDetection/ppdet/core/workspace.py\", line 143, in merge_config\r\n    dct['train_batch_size'] = dct['TrainReader']['batch_size']\r\nKeyError: 'batch_size'\n", "before_files": [{"content": "# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom __future__ import absolute_import\nfrom __future__ import print_function\nfrom __future__ import division\n\nimport importlib\nimport os\nimport sys\n\nimport yaml\nimport copy\nimport collections\n\nfrom .config.schema import SchemaDict, SharedConfig, extract_schema\nfrom .config.yaml_helpers import serializable\n\n__all__ = [\n    'global_config',\n    'load_config',\n    'merge_config',\n    'get_registered_modules',\n    'create',\n    'register',\n    'serializable',\n    'dump_value',\n]\n\n\ndef dump_value(value):\n    # XXX this is hackish, but collections.abc is not available in python 2\n    if hasattr(value, '__dict__') or isinstance(value, (dict, tuple, list)):\n        value = yaml.dump(value, default_flow_style=True)\n        value = value.replace('\\n', '')\n        value = value.replace('...', '')\n        return \"'{}'\".format(value)\n    else:\n        # primitive types\n        return str(value)\n\n\nclass AttrDict(dict):\n    \"\"\"Single level attribute dict, NOT recursive\"\"\"\n\n    def __init__(self, **kwargs):\n        super(AttrDict, self).__init__()\n        super(AttrDict, self).update(kwargs)\n\n    def __getattr__(self, key):\n        if key in self:\n            return self[key]\n        raise AttributeError(\"object has no attribute '{}'\".format(key))\n\n\nglobal_config = AttrDict()\n\nREADER_KEY = '_READER_'\n\n\ndef load_config(file_path):\n    \"\"\"\n    Load config from file.\n\n    Args:\n        file_path (str): Path of the config file to be loaded.\n\n    Returns: global config\n    \"\"\"\n    _, ext = os.path.splitext(file_path)\n    assert ext in ['.yml', '.yaml'], \"only support yaml files for now\"\n\n    cfg = AttrDict()\n    with open(file_path) as f:\n        cfg = merge_config(yaml.load(f, Loader=yaml.Loader), cfg)\n\n    if READER_KEY in cfg:\n        reader_cfg = cfg[READER_KEY]\n        if reader_cfg.startswith(\"~\"):\n            reader_cfg = os.path.expanduser(reader_cfg)\n        if not reader_cfg.startswith('/'):\n            reader_cfg = os.path.join(os.path.dirname(file_path), reader_cfg)\n\n        with open(reader_cfg) as f:\n            merge_config(yaml.load(f, Loader=yaml.Loader))\n        del cfg[READER_KEY]\n\n    merge_config(cfg)\n\n    return global_config\n\n\ndef dict_merge(dct, merge_dct):\n    \"\"\" Recursive dict merge. Inspired by :meth:``dict.update()``, instead of\n    updating only top-level keys, dict_merge recurses down into dicts nested\n    to an arbitrary depth, updating keys. The ``merge_dct`` is merged into\n    ``dct``.\n\n    Args:\n        dct: dict onto which the merge is executed\n        merge_dct: dct merged into dct\n\n    Returns: dct\n    \"\"\"\n    for k, v in merge_dct.items():\n        if (k in dct and isinstance(dct[k], dict) and\n                isinstance(merge_dct[k], collections.Mapping)):\n            dict_merge(dct[k], merge_dct[k])\n        else:\n            dct[k] = merge_dct[k]\n    return dct\n\n\ndef merge_config(config, another_cfg=None):\n    \"\"\"\n    Merge config into global config or another_cfg.\n\n    Args:\n        config (dict): Config to be merged.\n\n    Returns: global config\n    \"\"\"\n    global global_config\n    dct = another_cfg if another_cfg is not None else global_config\n    dct = dict_merge(dct, config)\n\n    # NOTE: training batch size defined only in TrainReader, sychornized\n    #       batch size config to global, models can get batch size config\n    #       from global config when building model.\n    #       batch size in evaluation or inference can also be added here\n    if 'TrainReader' in dct:\n        dct['train_batch_size'] = dct['TrainReader']['batch_size']\n\n    return dct\n\n\ndef get_registered_modules():\n    return {k: v for k, v in global_config.items() if isinstance(v, SchemaDict)}\n\n\ndef make_partial(cls):\n    if isinstance(cls.__op__, str):\n        sep = cls.__op__.split('.')\n        op_name = sep[-1]\n        op_module = importlib.import_module('.'.join(sep[:-1]))\n    else:\n        op_name = cls.__op__.__name__\n        op_module = importlib.import_module(cls.__op__.__module__)\n\n    if not hasattr(op_module, op_name):\n        import logging\n        logger = logging.getLogger(__name__)\n        logger.warn('{} OP not found, maybe a newer version of paddle '\n                    'is required.'.format(cls.__op__))\n        return cls\n\n    op = getattr(op_module, op_name)\n    cls.__category__ = getattr(cls, '__category__', None) or 'op'\n\n    def partial_apply(self, *args, **kwargs):\n        kwargs_ = self.__dict__.copy()\n        kwargs_.update(kwargs)\n        return op(*args, **kwargs_)\n\n    if getattr(cls, '__append_doc__', True):  # XXX should default to True?\n        if sys.version_info[0] > 2:\n            cls.__doc__ = \"Wrapper for `{}` OP\".format(op.__name__)\n            cls.__init__.__doc__ = op.__doc__\n            cls.__call__ = partial_apply\n            cls.__call__.__doc__ = op.__doc__\n        else:\n            # XXX work around for python 2\n            partial_apply.__doc__ = op.__doc__\n            cls.__call__ = partial_apply\n    return cls\n\n\ndef register(cls):\n    \"\"\"\n    Register a given module class.\n\n    Args:\n        cls (type): Module class to be registered.\n\n    Returns: cls\n    \"\"\"\n    if cls.__name__ in global_config:\n        raise ValueError(\"Module class already registered: {}\".format(\n            cls.__name__))\n    if hasattr(cls, '__op__'):\n        cls = make_partial(cls)\n    global_config[cls.__name__] = extract_schema(cls)\n    return cls\n\n\ndef create(cls_or_name, **kwargs):\n    \"\"\"\n    Create an instance of given module class.\n\n    Args:\n        cls_or_name (type or str): Class of which to create instance.\n\n    Returns: instance of type `cls_or_name`\n    \"\"\"\n    assert type(cls_or_name) in [type, str\n                                 ], \"should be a class or name of a class\"\n    name = type(cls_or_name) == str and cls_or_name or cls_or_name.__name__\n    assert name in global_config and \\\n        isinstance(global_config[name], SchemaDict), \\\n        \"the module {} is not registered\".format(name)\n    config = global_config[name]\n    config.update(kwargs)\n    config.validate()\n    cls = getattr(config.pymodule, name)\n\n    kwargs = {}\n    kwargs.update(global_config[name])\n\n    # parse `shared` annoation of registered modules\n    if getattr(config, 'shared', None):\n        for k in config.shared:\n            target_key = config[k]\n            shared_conf = config.schema[k].default\n            assert isinstance(shared_conf, SharedConfig)\n            if target_key is not None and not isinstance(target_key,\n                                                         SharedConfig):\n                continue  # value is given for the module\n            elif shared_conf.key in global_config:\n                # `key` is present in config\n                kwargs[k] = global_config[shared_conf.key]\n            else:\n                kwargs[k] = shared_conf.default_value\n\n    # parse `inject` annoation of registered modules\n    if getattr(config, 'inject', None):\n        for k in config.inject:\n            target_key = config[k]\n            # optional dependency\n            if target_key is None:\n                continue\n            # also accept dictionaries and serialized objects\n            if isinstance(target_key, dict) or hasattr(target_key, '__dict__'):\n                continue\n            elif isinstance(target_key, str):\n                if target_key not in global_config:\n                    raise ValueError(\"Missing injection config:\", target_key)\n                target = global_config[target_key]\n                if isinstance(target, SchemaDict):\n                    kwargs[k] = create(target_key)\n                elif hasattr(target, '__dict__'):  # serialized object\n                    kwargs[k] = target\n            else:\n                raise ValueError(\"Unsupported injection type:\", target_key)\n    # prevent modification of global config values of reference types\n    # (e.g., list, dict) from within the created module instances\n    kwargs = copy.deepcopy(kwargs)\n    return cls(**kwargs)\n", "path": "ppdet/core/workspace.py"}], "after_files": [{"content": "# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom __future__ import absolute_import\nfrom __future__ import print_function\nfrom __future__ import division\n\nimport importlib\nimport os\nimport sys\n\nimport yaml\nimport copy\nimport collections\n\nfrom .config.schema import SchemaDict, SharedConfig, extract_schema\nfrom .config.yaml_helpers import serializable\n\n__all__ = [\n    'global_config',\n    'load_config',\n    'merge_config',\n    'get_registered_modules',\n    'create',\n    'register',\n    'serializable',\n    'dump_value',\n]\n\n\ndef dump_value(value):\n    # XXX this is hackish, but collections.abc is not available in python 2\n    if hasattr(value, '__dict__') or isinstance(value, (dict, tuple, list)):\n        value = yaml.dump(value, default_flow_style=True)\n        value = value.replace('\\n', '')\n        value = value.replace('...', '')\n        return \"'{}'\".format(value)\n    else:\n        # primitive types\n        return str(value)\n\n\nclass AttrDict(dict):\n    \"\"\"Single level attribute dict, NOT recursive\"\"\"\n\n    def __init__(self, **kwargs):\n        super(AttrDict, self).__init__()\n        super(AttrDict, self).update(kwargs)\n\n    def __getattr__(self, key):\n        if key in self:\n            return self[key]\n        raise AttributeError(\"object has no attribute '{}'\".format(key))\n\n\nglobal_config = AttrDict()\n\nREADER_KEY = '_READER_'\n\n\ndef load_config(file_path):\n    \"\"\"\n    Load config from file.\n\n    Args:\n        file_path (str): Path of the config file to be loaded.\n\n    Returns: global config\n    \"\"\"\n    _, ext = os.path.splitext(file_path)\n    assert ext in ['.yml', '.yaml'], \"only support yaml files for now\"\n\n    cfg = AttrDict()\n    with open(file_path) as f:\n        cfg = merge_config(yaml.load(f, Loader=yaml.Loader), cfg)\n\n    if READER_KEY in cfg:\n        reader_cfg = cfg[READER_KEY]\n        if reader_cfg.startswith(\"~\"):\n            reader_cfg = os.path.expanduser(reader_cfg)\n        if not reader_cfg.startswith('/'):\n            reader_cfg = os.path.join(os.path.dirname(file_path), reader_cfg)\n\n        with open(reader_cfg) as f:\n            merge_config(yaml.load(f, Loader=yaml.Loader))\n        del cfg[READER_KEY]\n\n    merge_config(cfg)\n\n    return global_config\n\n\ndef dict_merge(dct, merge_dct):\n    \"\"\" Recursive dict merge. Inspired by :meth:``dict.update()``, instead of\n    updating only top-level keys, dict_merge recurses down into dicts nested\n    to an arbitrary depth, updating keys. The ``merge_dct`` is merged into\n    ``dct``.\n\n    Args:\n        dct: dict onto which the merge is executed\n        merge_dct: dct merged into dct\n\n    Returns: dct\n    \"\"\"\n    for k, v in merge_dct.items():\n        if (k in dct and isinstance(dct[k], dict) and\n                isinstance(merge_dct[k], collections.Mapping)):\n            dict_merge(dct[k], merge_dct[k])\n        else:\n            dct[k] = merge_dct[k]\n    return dct\n\n\ndef merge_config(config, another_cfg=None):\n    \"\"\"\n    Merge config into global config or another_cfg.\n\n    Args:\n        config (dict): Config to be merged.\n\n    Returns: global config\n    \"\"\"\n    global global_config\n    dct = another_cfg if another_cfg is not None else global_config\n    dct = dict_merge(dct, config)\n\n    # NOTE: training batch size defined only in TrainReader, sychornized\n    #       batch size config to global, models can get batch size config\n    #       from global config when building model.\n    #       batch size in evaluation or inference can also be added here\n    if 'TrainReader' in dct and 'batch_size' in dct['TrainReader']:\n        dct['train_batch_size'] = dct['TrainReader']['batch_size']\n\n    return dct\n\n\ndef get_registered_modules():\n    return {k: v for k, v in global_config.items() if isinstance(v, SchemaDict)}\n\n\ndef make_partial(cls):\n    if isinstance(cls.__op__, str):\n        sep = cls.__op__.split('.')\n        op_name = sep[-1]\n        op_module = importlib.import_module('.'.join(sep[:-1]))\n    else:\n        op_name = cls.__op__.__name__\n        op_module = importlib.import_module(cls.__op__.__module__)\n\n    if not hasattr(op_module, op_name):\n        import logging\n        logger = logging.getLogger(__name__)\n        logger.warn('{} OP not found, maybe a newer version of paddle '\n                    'is required.'.format(cls.__op__))\n        return cls\n\n    op = getattr(op_module, op_name)\n    cls.__category__ = getattr(cls, '__category__', None) or 'op'\n\n    def partial_apply(self, *args, **kwargs):\n        kwargs_ = self.__dict__.copy()\n        kwargs_.update(kwargs)\n        return op(*args, **kwargs_)\n\n    if getattr(cls, '__append_doc__', True):  # XXX should default to True?\n        if sys.version_info[0] > 2:\n            cls.__doc__ = \"Wrapper for `{}` OP\".format(op.__name__)\n            cls.__init__.__doc__ = op.__doc__\n            cls.__call__ = partial_apply\n            cls.__call__.__doc__ = op.__doc__\n        else:\n            # XXX work around for python 2\n            partial_apply.__doc__ = op.__doc__\n            cls.__call__ = partial_apply\n    return cls\n\n\ndef register(cls):\n    \"\"\"\n    Register a given module class.\n\n    Args:\n        cls (type): Module class to be registered.\n\n    Returns: cls\n    \"\"\"\n    if cls.__name__ in global_config:\n        raise ValueError(\"Module class already registered: {}\".format(\n            cls.__name__))\n    if hasattr(cls, '__op__'):\n        cls = make_partial(cls)\n    global_config[cls.__name__] = extract_schema(cls)\n    return cls\n\n\ndef create(cls_or_name, **kwargs):\n    \"\"\"\n    Create an instance of given module class.\n\n    Args:\n        cls_or_name (type or str): Class of which to create instance.\n\n    Returns: instance of type `cls_or_name`\n    \"\"\"\n    assert type(cls_or_name) in [type, str\n                                 ], \"should be a class or name of a class\"\n    name = type(cls_or_name) == str and cls_or_name or cls_or_name.__name__\n    assert name in global_config and \\\n        isinstance(global_config[name], SchemaDict), \\\n        \"the module {} is not registered\".format(name)\n    config = global_config[name]\n    config.update(kwargs)\n    config.validate()\n    cls = getattr(config.pymodule, name)\n\n    kwargs = {}\n    kwargs.update(global_config[name])\n\n    # parse `shared` annoation of registered modules\n    if getattr(config, 'shared', None):\n        for k in config.shared:\n            target_key = config[k]\n            shared_conf = config.schema[k].default\n            assert isinstance(shared_conf, SharedConfig)\n            if target_key is not None and not isinstance(target_key,\n                                                         SharedConfig):\n                continue  # value is given for the module\n            elif shared_conf.key in global_config:\n                # `key` is present in config\n                kwargs[k] = global_config[shared_conf.key]\n            else:\n                kwargs[k] = shared_conf.default_value\n\n    # parse `inject` annoation of registered modules\n    if getattr(config, 'inject', None):\n        for k in config.inject:\n            target_key = config[k]\n            # optional dependency\n            if target_key is None:\n                continue\n            # also accept dictionaries and serialized objects\n            if isinstance(target_key, dict) or hasattr(target_key, '__dict__'):\n                continue\n            elif isinstance(target_key, str):\n                if target_key not in global_config:\n                    raise ValueError(\"Missing injection config:\", target_key)\n                target = global_config[target_key]\n                if isinstance(target, SchemaDict):\n                    kwargs[k] = create(target_key)\n                elif hasattr(target, '__dict__'):  # serialized object\n                    kwargs[k] = target\n            else:\n                raise ValueError(\"Unsupported injection type:\", target_key)\n    # prevent modification of global config values of reference types\n    # (e.g., list, dict) from within the created module instances\n    kwargs = copy.deepcopy(kwargs)\n    return cls(**kwargs)\n", "path": "ppdet/core/workspace.py"}]}