prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  tiledb.open doesn't accept an optional ctx
  it accepts a config which creates a ctx, would it make sense to have both?
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `tiledb/highlevel.py`
  Content:
  ```
  1 import tiledb
  2 from tiledb.libtiledb import *
  3 
  4 import numpy as np
  5 
  6 def open(uri, key=None, attr=None, mode='r', config=None):
  7     """
  8     Open a TileDB array at the given URI
  9 
  10     :param uri: any TileDB supported URI
  11     :param key: encryption key, str or None
  12     :param str mode: (default 'r') Open the array object in read 'r' or write 'w' mode
  13     :param attr: attribute name to select from a multi-attribute array, str or None
  14     :param config: TileDB config dictionary, dict or None
  15     :return:
  16     """
  17     if config:
  18         cfg = tiledb.Config(config)
  19         ctx = tiledb.Ctx(cfg)
  20     else:
  21         ctx = default_ctx()
  22 
  23     schema = ArraySchema.load(uri, ctx=ctx)
  24     if not schema:
  25         raise Exception("Unable to load tiledb ArraySchema from URI: '{}'".format(uri))
  26 
  27     if schema.sparse:
  28         return tiledb.SparseArray(uri, mode=mode, key=key, attr=attr, ctx=ctx)
  29     elif not schema.sparse:
  30         return tiledb.DenseArray(uri, mode=mode, key=key, attr=attr, ctx=ctx)
  31     else:
  32         raise Exception("Unknown TileDB array type")
  33 
  34 
  35 def save(uri, array, config=None, **kw):
  36     """
  37     Save array-like object at the given URI.
  38 
  39     :param uri: str or None
  40     :param array: array-like object convertible to NumPy
  41     :param config: TileDB config dictionary, dict or None
  42     :param kw: optional keyword args will be forwarded to tiledb.Array constructor
  43     :return:
  44     """
  45     if not isinstance(array, np.ndarray):
  46         raise ValueError("expected NumPy ndarray, not '{}'".format(type(array)))
  47     if config:
  48         cfg = Config(config)
  49         ctx = tiledb.Ctx(cfg)
  50     else:
  51         ctx = default_ctx()
  52 
  53     return tiledb.from_numpy(uri, array, ctx=ctx)
  54 
  55 
  56 def empty_like(uri, arr, config=None, key=None, tile=None):
  57     """
  58     Create and return an empty, writeable DenseArray with schema based on
  59     a NumPy-array like object.
  60 
  61     :param uri:
  62     :param arr: NumPy ndarray, or shape tuple
  63     :param ctx:
  64     :param kw:
  65     :return:
  66     """
  67     if config:
  68         cfg = tiledb.Config(config)
  69         ctx = tiledb.Ctx(cfg)
  70     else:
  71         ctx = default_ctx()
  72 
  73     if arr is ArraySchema:
  74         schema = arr
  75     else:
  76         schema = schema_like(arr, tile=tile, ctx=ctx)
  77 
  78     tiledb.DenseArray.create(uri, key=key, schema=schema)
  79     return tiledb.DenseArray(uri, mode='w', key=key, ctx=ctx)
  80 
  81 
  82 def from_numpy(uri, array, ctx=default_ctx(), **kw):
  83     """
  84     Convenience method, see `tiledb.DenseArray.from_numpy`
  85     """
  86     if not isinstance(array, np.ndarray):
  87         raise Exception("from_numpy is only currently supported for numpy.ndarray")
  88 
  89     return DenseArray.from_numpy(uri, array, ctx=ctx, **kw)
  90 
  91
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/tiledb/highlevel.py b/tiledb/highlevel.py
  --- a/tiledb/highlevel.py
  +++ b/tiledb/highlevel.py
  @@ -3,7 +3,7 @@
   
   import numpy as np
   
  -def open(uri, key=None, attr=None, mode='r', config=None):
  +def open(uri, key=None, attr=None, mode='r', config=None, ctx=None):
       """
       Open a TileDB array at the given URI
   
  @@ -14,10 +14,14 @@
       :param config: TileDB config dictionary, dict or None
       :return:
       """
  +    if ctx and config:
  +      raise ValueError("Received extra Ctx or Config argument: either one may be provided, but not both")
  +
       if config:
           cfg = tiledb.Config(config)
           ctx = tiledb.Ctx(cfg)
  -    else:
  +
  +    if ctx is None:
           ctx = default_ctx()
   
       schema = ArraySchema.load(uri, ctx=ctx)
  @@ -88,3 +92,23 @@
   
       return DenseArray.from_numpy(uri, array, ctx=ctx, **kw)
   
  +def array_exists(uri, isdense=False, issparse=False):
  +    """
  +    Check if arrays exists and is open-able at the given URI
  +
  +    Optionally restrict to `isdense` or `issparse` array types.
  +    """
  +    try:
  +        a = tiledb.open(uri)
  +    except TileDBError as exc:
  +        return False
  +
  +    if isdense:
  +        rval = not a.schema.sparse
  +    elif issparse:
  +        rval = a.schema.sparse
  +    else:
  +        rval = True
  +
  +    a.close()
  +    return rval
  
verification_info: {"golden_diff": "diff --git a/tiledb/highlevel.py b/tiledb/highlevel.py\n--- a/tiledb/highlevel.py\n+++ b/tiledb/highlevel.py\n@@ -3,7 +3,7 @@\n \n import numpy as np\n \n-def open(uri, key=None, attr=None, mode='r', config=None):\n+def open(uri, key=None, attr=None, mode='r', config=None, ctx=None):\n     \"\"\"\n     Open a TileDB array at the given URI\n \n@@ -14,10 +14,14 @@\n     :param config: TileDB config dictionary, dict or None\n     :return:\n     \"\"\"\n+    if ctx and config:\n+      raise ValueError(\"Received extra Ctx or Config argument: either one may be provided, but not both\")\n+\n     if config:\n         cfg = tiledb.Config(config)\n         ctx = tiledb.Ctx(cfg)\n-    else:\n+\n+    if ctx is None:\n         ctx = default_ctx()\n \n     schema = ArraySchema.load(uri, ctx=ctx)\n@@ -88,3 +92,23 @@\n \n     return DenseArray.from_numpy(uri, array, ctx=ctx, **kw)\n \n+def array_exists(uri, isdense=False, issparse=False):\n+    \"\"\"\n+    Check if arrays exists and is open-able at the given URI\n+\n+    Optionally restrict to `isdense` or `issparse` array types.\n+    \"\"\"\n+    try:\n+        a = tiledb.open(uri)\n+    except TileDBError as exc:\n+        return False\n+\n+    if isdense:\n+        rval = not a.schema.sparse\n+    elif issparse:\n+        rval = a.schema.sparse\n+    else:\n+        rval = True\n+\n+    a.close()\n+    return rval\n", "issue": "tiledb.open doesn't accept an optional ctx\nit accepts a config which creates a ctx, would it make sense to have both?\n", "before_files": [{"content": "import tiledb\nfrom tiledb.libtiledb import *\n\nimport numpy as np\n\ndef open(uri, key=None, attr=None, mode='r', config=None):\n    \"\"\"\n    Open a TileDB array at the given URI\n\n    :param uri: any TileDB supported URI\n    :param key: encryption key, str or None\n    :param str mode: (default 'r') Open the array object in read 'r' or write 'w' mode\n    :param attr: attribute name to select from a multi-attribute array, str or None\n    :param config: TileDB config dictionary, dict or None\n    :return:\n    \"\"\"\n    if config:\n        cfg = tiledb.Config(config)\n        ctx = tiledb.Ctx(cfg)\n    else:\n        ctx = default_ctx()\n\n    schema = ArraySchema.load(uri, ctx=ctx)\n    if not schema:\n        raise Exception(\"Unable to load tiledb ArraySchema from URI: '{}'\".format(uri))\n\n    if schema.sparse:\n        return tiledb.SparseArray(uri, mode=mode, key=key, attr=attr, ctx=ctx)\n    elif not schema.sparse:\n        return tiledb.DenseArray(uri, mode=mode, key=key, attr=attr, ctx=ctx)\n    else:\n        raise Exception(\"Unknown TileDB array type\")\n\n\ndef save(uri, array, config=None, **kw):\n    \"\"\"\n    Save array-like object at the given URI.\n\n    :param uri: str or None\n    :param array: array-like object convertible to NumPy\n    :param config: TileDB config dictionary, dict or None\n    :param kw: optional keyword args will be forwarded to tiledb.Array constructor\n    :return:\n    \"\"\"\n    if not isinstance(array, np.ndarray):\n        raise ValueError(\"expected NumPy ndarray, not '{}'\".format(type(array)))\n    if config:\n        cfg = Config(config)\n        ctx = tiledb.Ctx(cfg)\n    else:\n        ctx = default_ctx()\n\n    return tiledb.from_numpy(uri, array, ctx=ctx)\n\n\ndef empty_like(uri, arr, config=None, key=None, tile=None):\n    \"\"\"\n    Create and return an empty, writeable DenseArray with schema based on\n    a NumPy-array like object.\n\n    :param uri:\n    :param arr: NumPy ndarray, or shape tuple\n    :param ctx:\n    :param kw:\n    :return:\n    \"\"\"\n    if config:\n        cfg = tiledb.Config(config)\n        ctx = tiledb.Ctx(cfg)\n    else:\n        ctx = default_ctx()\n\n    if arr is ArraySchema:\n        schema = arr\n    else:\n        schema = schema_like(arr, tile=tile, ctx=ctx)\n\n    tiledb.DenseArray.create(uri, key=key, schema=schema)\n    return tiledb.DenseArray(uri, mode='w', key=key, ctx=ctx)\n\n\ndef from_numpy(uri, array, ctx=default_ctx(), **kw):\n    \"\"\"\n    Convenience method, see `tiledb.DenseArray.from_numpy`\n    \"\"\"\n    if not isinstance(array, np.ndarray):\n        raise Exception(\"from_numpy is only currently supported for numpy.ndarray\")\n\n    return DenseArray.from_numpy(uri, array, ctx=ctx, **kw)\n\n", "path": "tiledb/highlevel.py"}], "after_files": [{"content": "import tiledb\nfrom tiledb.libtiledb import *\n\nimport numpy as np\n\ndef open(uri, key=None, attr=None, mode='r', config=None, ctx=None):\n    \"\"\"\n    Open a TileDB array at the given URI\n\n    :param uri: any TileDB supported URI\n    :param key: encryption key, str or None\n    :param str mode: (default 'r') Open the array object in read 'r' or write 'w' mode\n    :param attr: attribute name to select from a multi-attribute array, str or None\n    :param config: TileDB config dictionary, dict or None\n    :return:\n    \"\"\"\n    if ctx and config:\n      raise ValueError(\"Received extra Ctx or Config argument: either one may be provided, but not both\")\n\n    if config:\n        cfg = tiledb.Config(config)\n        ctx = tiledb.Ctx(cfg)\n\n    if ctx is None:\n        ctx = default_ctx()\n\n    schema = ArraySchema.load(uri, ctx=ctx)\n    if not schema:\n        raise Exception(\"Unable to load tiledb ArraySchema from URI: '{}'\".format(uri))\n\n    if schema.sparse:\n        return tiledb.SparseArray(uri, mode=mode, key=key, attr=attr, ctx=ctx)\n    elif not schema.sparse:\n        return tiledb.DenseArray(uri, mode=mode, key=key, attr=attr, ctx=ctx)\n    else:\n        raise Exception(\"Unknown TileDB array type\")\n\n\ndef save(uri, array, config=None, **kw):\n    \"\"\"\n    Save array-like object at the given URI.\n\n    :param uri: str or None\n    :param array: array-like object convertible to NumPy\n    :param config: TileDB config dictionary, dict or None\n    :param kw: optional keyword args will be forwarded to tiledb.Array constructor\n    :return:\n    \"\"\"\n    if not isinstance(array, np.ndarray):\n        raise ValueError(\"expected NumPy ndarray, not '{}'\".format(type(array)))\n    if config:\n        cfg = Config(config)\n        ctx = tiledb.Ctx(cfg)\n    else:\n        ctx = default_ctx()\n\n    return tiledb.from_numpy(uri, array, ctx=ctx)\n\n\ndef empty_like(uri, arr, config=None, key=None, tile=None):\n    \"\"\"\n    Create and return an empty, writeable DenseArray with schema based on\n    a NumPy-array like object.\n\n    :param uri:\n    :param arr: NumPy ndarray, or shape tuple\n    :param ctx:\n    :param kw:\n    :return:\n    \"\"\"\n    if config:\n        cfg = tiledb.Config(config)\n        ctx = tiledb.Ctx(cfg)\n    else:\n        ctx = default_ctx()\n\n    if arr is ArraySchema:\n        schema = arr\n    else:\n        schema = schema_like(arr, tile=tile, ctx=ctx)\n\n    tiledb.DenseArray.create(uri, key=key, schema=schema)\n    return tiledb.DenseArray(uri, mode='w', key=key, ctx=ctx)\n\n\ndef from_numpy(uri, array, ctx=default_ctx(), **kw):\n    \"\"\"\n    Convenience method, see `tiledb.DenseArray.from_numpy`\n    \"\"\"\n    if not isinstance(array, np.ndarray):\n        raise Exception(\"from_numpy is only currently supported for numpy.ndarray\")\n\n    return DenseArray.from_numpy(uri, array, ctx=ctx, **kw)\n\ndef array_exists(uri, isdense=False, issparse=False):\n    \"\"\"\n    Check if arrays exists and is open-able at the given URI\n\n    Optionally restrict to `isdense` or `issparse` array types.\n    \"\"\"\n    try:\n        a = tiledb.open(uri)\n    except TileDBError as exc:\n        return False\n\n    if isdense:\n        rval = not a.schema.sparse\n    elif issparse:\n        rval = a.schema.sparse\n    else:\n        rval = True\n\n    a.close()\n    return rval\n", "path": "tiledb/highlevel.py"}]}