prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  [tune[ partial function cannot be registered as trainable
  ### System information
  - **OS Platform and Distribution (e.g., Linux Ubuntu 16.04)**: Ubuntu 18.04
  - **Ray installed from (source or binary)**: binary
  - **Ray version**: 0.6.1
  - **Python version**: 3.7
  - **Exact command to reproduce**:
  
  The following code fails:
  ```
  def dummy_fn(c, a, b):
      print("Called")
  
  from functools import partial
  from ray.tune import register_trainable
  register_trainable("test", partial(dummy_fn, c=None))
  
  ```
  
  while the following code works:
  ```
  def dummy_fn(a, b):
      print("Called")
  
  from functools import partial
  from ray.tune import register_trainable
  register_trainable("test", dummy_fn)
  
  ```
  ### Describe the problem
  The first code sample does not work, despite the function (after the `partial`) fullfills all requirements to be properly registered.
  
  ### Source code / logs
  Traceback:
  
  ```
  Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "/home/temp/schock/conda/envs/delira_new/lib/python3.7/site-packages/ray/tune/registry.py", line 35, in register_trainable
      if not issubclass(trainable, Trainable):
  TypeError: issubclass() arg 1 must be a class
  ```
  
  
  </issue>
  <code>
  [start of python/ray/tune/registry.py]
  1 from __future__ import absolute_import
  2 from __future__ import division
  3 from __future__ import print_function
  4 
  5 from types import FunctionType
  6 
  7 import ray
  8 import ray.cloudpickle as pickle
  9 from ray.experimental.internal_kv import _internal_kv_initialized, \
  10     _internal_kv_get, _internal_kv_put
  11 
  12 TRAINABLE_CLASS = "trainable_class"
  13 ENV_CREATOR = "env_creator"
  14 RLLIB_MODEL = "rllib_model"
  15 RLLIB_PREPROCESSOR = "rllib_preprocessor"
  16 KNOWN_CATEGORIES = [
  17     TRAINABLE_CLASS, ENV_CREATOR, RLLIB_MODEL, RLLIB_PREPROCESSOR
  18 ]
  19 
  20 
  21 def register_trainable(name, trainable):
  22     """Register a trainable function or class.
  23 
  24     Args:
  25         name (str): Name to register.
  26         trainable (obj): Function or tune.Trainable class. Functions must
  27             take (config, status_reporter) as arguments and will be
  28             automatically converted into a class during registration.
  29     """
  30 
  31     from ray.tune.trainable import Trainable, wrap_function
  32 
  33     if isinstance(trainable, FunctionType):
  34         trainable = wrap_function(trainable)
  35     if not issubclass(trainable, Trainable):
  36         raise TypeError("Second argument must be convertable to Trainable",
  37                         trainable)
  38     _global_registry.register(TRAINABLE_CLASS, name, trainable)
  39 
  40 
  41 def register_env(name, env_creator):
  42     """Register a custom environment for use with RLlib.
  43 
  44     Args:
  45         name (str): Name to register.
  46         env_creator (obj): Function that creates an env.
  47     """
  48 
  49     if not isinstance(env_creator, FunctionType):
  50         raise TypeError("Second argument must be a function.", env_creator)
  51     _global_registry.register(ENV_CREATOR, name, env_creator)
  52 
  53 
  54 def _make_key(category, key):
  55     """Generate a binary key for the given category and key.
  56 
  57     Args:
  58         category (str): The category of the item
  59         key (str): The unique identifier for the item
  60 
  61     Returns:
  62         The key to use for storing a the value.
  63     """
  64     return (b"TuneRegistry:" + category.encode("ascii") + b"/" +
  65             key.encode("ascii"))
  66 
  67 
  68 class _Registry(object):
  69     def __init__(self):
  70         self._to_flush = {}
  71 
  72     def register(self, category, key, value):
  73         if category not in KNOWN_CATEGORIES:
  74             from ray.tune import TuneError
  75             raise TuneError("Unknown category {} not among {}".format(
  76                 category, KNOWN_CATEGORIES))
  77         self._to_flush[(category, key)] = pickle.dumps(value)
  78         if _internal_kv_initialized():
  79             self.flush_values()
  80 
  81     def contains(self, category, key):
  82         if _internal_kv_initialized():
  83             value = _internal_kv_get(_make_key(category, key))
  84             return value is not None
  85         else:
  86             return (category, key) in self._to_flush
  87 
  88     def get(self, category, key):
  89         if _internal_kv_initialized():
  90             value = _internal_kv_get(_make_key(category, key))
  91             if value is None:
  92                 raise ValueError(
  93                     "Registry value for {}/{} doesn't exist.".format(
  94                         category, key))
  95             return pickle.loads(value)
  96         else:
  97             return pickle.loads(self._to_flush[(category, key)])
  98 
  99     def flush_values(self):
  100         for (category, key), value in self._to_flush.items():
  101             _internal_kv_put(_make_key(category, key), value, overwrite=True)
  102         self._to_flush.clear()
  103 
  104 
  105 _global_registry = _Registry()
  106 ray.worker._post_init_hooks.append(_global_registry.flush_values)
  107
  [end of python/ray/tune/registry.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/python/ray/tune/registry.py b/python/ray/tune/registry.py
  --- a/python/ray/tune/registry.py
  +++ b/python/ray/tune/registry.py
  @@ -2,6 +2,7 @@
   from __future__ import division
   from __future__ import print_function
   
  +import logging
   from types import FunctionType
   
   import ray
  @@ -17,6 +18,8 @@
       TRAINABLE_CLASS, ENV_CREATOR, RLLIB_MODEL, RLLIB_PREPROCESSOR
   ]
   
  +logger = logging.getLogger(__name__)
  +
   
   def register_trainable(name, trainable):
       """Register a trainable function or class.
  @@ -30,8 +33,16 @@
   
       from ray.tune.trainable import Trainable, wrap_function
   
  -    if isinstance(trainable, FunctionType):
  +    if isinstance(trainable, type):
  +        logger.debug("Detected class for trainable.")
  +    elif isinstance(trainable, FunctionType):
  +        logger.debug("Detected function for trainable.")
  +        trainable = wrap_function(trainable)
  +    elif callable(trainable):
  +        logger.warning(
  +            "Detected unknown callable for trainable. Converting to class.")
           trainable = wrap_function(trainable)
  +
       if not issubclass(trainable, Trainable):
           raise TypeError("Second argument must be convertable to Trainable",
                           trainable)
  
verification_info: {"golden_diff": "diff --git a/python/ray/tune/registry.py b/python/ray/tune/registry.py\n--- a/python/ray/tune/registry.py\n+++ b/python/ray/tune/registry.py\n@@ -2,6 +2,7 @@\n from __future__ import division\n from __future__ import print_function\n \n+import logging\n from types import FunctionType\n \n import ray\n@@ -17,6 +18,8 @@\n     TRAINABLE_CLASS, ENV_CREATOR, RLLIB_MODEL, RLLIB_PREPROCESSOR\n ]\n \n+logger = logging.getLogger(__name__)\n+\n \n def register_trainable(name, trainable):\n     \"\"\"Register a trainable function or class.\n@@ -30,8 +33,16 @@\n \n     from ray.tune.trainable import Trainable, wrap_function\n \n-    if isinstance(trainable, FunctionType):\n+    if isinstance(trainable, type):\n+        logger.debug(\"Detected class for trainable.\")\n+    elif isinstance(trainable, FunctionType):\n+        logger.debug(\"Detected function for trainable.\")\n+        trainable = wrap_function(trainable)\n+    elif callable(trainable):\n+        logger.warning(\n+            \"Detected unknown callable for trainable. Converting to class.\")\n         trainable = wrap_function(trainable)\n+\n     if not issubclass(trainable, Trainable):\n         raise TypeError(\"Second argument must be convertable to Trainable\",\n                         trainable)\n", "issue": "[tune[ partial function cannot be registered as trainable\n### System information\r\n- **OS Platform and Distribution (e.g., Linux Ubuntu 16.04)**: Ubuntu 18.04\r\n- **Ray installed from (source or binary)**: binary\r\n- **Ray version**: 0.6.1\r\n- **Python version**: 3.7\r\n- **Exact command to reproduce**:\r\n\r\nThe following code fails:\r\n```\r\ndef dummy_fn(c, a, b):\r\n    print(\"Called\")\r\n\r\nfrom functools import partial\r\nfrom ray.tune import register_trainable\r\nregister_trainable(\"test\", partial(dummy_fn, c=None))\r\n\r\n```\r\n\r\nwhile the following code works:\r\n```\r\ndef dummy_fn(a, b):\r\n    print(\"Called\")\r\n\r\nfrom functools import partial\r\nfrom ray.tune import register_trainable\r\nregister_trainable(\"test\", dummy_fn)\r\n\r\n```\r\n### Describe the problem\r\nThe first code sample does not work, despite the function (after the `partial`) fullfills all requirements to be properly registered.\r\n\r\n### Source code / logs\r\nTraceback:\r\n\r\n```\r\nTraceback (most recent call last):\r\n  File \"<stdin>\", line 1, in <module>\r\n  File \"/home/temp/schock/conda/envs/delira_new/lib/python3.7/site-packages/ray/tune/registry.py\", line 35, in register_trainable\r\n    if not issubclass(trainable, Trainable):\r\nTypeError: issubclass() arg 1 must be a class\r\n```\r\n\n", "before_files": [{"content": "from __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\nfrom types import FunctionType\n\nimport ray\nimport ray.cloudpickle as pickle\nfrom ray.experimental.internal_kv import _internal_kv_initialized, \\\n    _internal_kv_get, _internal_kv_put\n\nTRAINABLE_CLASS = \"trainable_class\"\nENV_CREATOR = \"env_creator\"\nRLLIB_MODEL = \"rllib_model\"\nRLLIB_PREPROCESSOR = \"rllib_preprocessor\"\nKNOWN_CATEGORIES = [\n    TRAINABLE_CLASS, ENV_CREATOR, RLLIB_MODEL, RLLIB_PREPROCESSOR\n]\n\n\ndef register_trainable(name, trainable):\n    \"\"\"Register a trainable function or class.\n\n    Args:\n        name (str): Name to register.\n        trainable (obj): Function or tune.Trainable class. Functions must\n            take (config, status_reporter) as arguments and will be\n            automatically converted into a class during registration.\n    \"\"\"\n\n    from ray.tune.trainable import Trainable, wrap_function\n\n    if isinstance(trainable, FunctionType):\n        trainable = wrap_function(trainable)\n    if not issubclass(trainable, Trainable):\n        raise TypeError(\"Second argument must be convertable to Trainable\",\n                        trainable)\n    _global_registry.register(TRAINABLE_CLASS, name, trainable)\n\n\ndef register_env(name, env_creator):\n    \"\"\"Register a custom environment for use with RLlib.\n\n    Args:\n        name (str): Name to register.\n        env_creator (obj): Function that creates an env.\n    \"\"\"\n\n    if not isinstance(env_creator, FunctionType):\n        raise TypeError(\"Second argument must be a function.\", env_creator)\n    _global_registry.register(ENV_CREATOR, name, env_creator)\n\n\ndef _make_key(category, key):\n    \"\"\"Generate a binary key for the given category and key.\n\n    Args:\n        category (str): The category of the item\n        key (str): The unique identifier for the item\n\n    Returns:\n        The key to use for storing a the value.\n    \"\"\"\n    return (b\"TuneRegistry:\" + category.encode(\"ascii\") + b\"/\" +\n            key.encode(\"ascii\"))\n\n\nclass _Registry(object):\n    def __init__(self):\n        self._to_flush = {}\n\n    def register(self, category, key, value):\n        if category not in KNOWN_CATEGORIES:\n            from ray.tune import TuneError\n            raise TuneError(\"Unknown category {} not among {}\".format(\n                category, KNOWN_CATEGORIES))\n        self._to_flush[(category, key)] = pickle.dumps(value)\n        if _internal_kv_initialized():\n            self.flush_values()\n\n    def contains(self, category, key):\n        if _internal_kv_initialized():\n            value = _internal_kv_get(_make_key(category, key))\n            return value is not None\n        else:\n            return (category, key) in self._to_flush\n\n    def get(self, category, key):\n        if _internal_kv_initialized():\n            value = _internal_kv_get(_make_key(category, key))\n            if value is None:\n                raise ValueError(\n                    \"Registry value for {}/{} doesn't exist.\".format(\n                        category, key))\n            return pickle.loads(value)\n        else:\n            return pickle.loads(self._to_flush[(category, key)])\n\n    def flush_values(self):\n        for (category, key), value in self._to_flush.items():\n            _internal_kv_put(_make_key(category, key), value, overwrite=True)\n        self._to_flush.clear()\n\n\n_global_registry = _Registry()\nray.worker._post_init_hooks.append(_global_registry.flush_values)\n", "path": "python/ray/tune/registry.py"}]}