prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  DeprecationWarning on `pkg_resources` in Python 3.10
  ### Expected behaviour
  ODC running in Python 3.10 shouldn't print `DeprecationWarning`s.
  
  ### Actual behaviour
  
  When running some ODC code:
  ```
    .../testenv/lib/python3.10/site-packages/datacube/drivers/driver_cache.py:54: DeprecationWarning: pkg_resources is deprecated as an API
      from pkg_resources import iter_entry_points
  ```
  Which is: https://github.com/opendatacube/datacube-core/blob/develop/datacube/drivers/driver_cache.py#L29
  
  This code should be replaced with modules from the Python standard library, see: [Package Discovery and Resource Access using pkg_resources - setuptools 68.0.0.post20230621 documentation](https://setuptools.pypa.io/en/latest/pkg_resources.html) and [importlib.resources – Resources — Python 3.11.4 documentation](https://docs.python.org/3/library/importlib.resources.html#module-importlib.resources).
  
  We've already set the minimum Python version as 3.8, and the stdlib modules exist since 3.7, so we don't need to add the external backports as dependencies.
  
  ### Environment information
  
  * Which ``datacube --version`` are you using?
     `Open Data Cube core, version 1.8.13`
  * What datacube deployment/enviornment are you running against?
     Local installation from conda-forge.
  
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `datacube/drivers/driver_cache.py`
  Content:
  ```
  1 # This file is part of the Open Data Cube, see https://opendatacube.org for more information
  2 #
  3 # Copyright (c) 2015-2023 ODC Contributors
  4 # SPDX-License-Identifier: Apache-2.0
  5 import logging
  6 from typing import Dict, Any, Tuple, Iterable
  7 
  8 _LOG = logging.getLogger(__name__)
  9 
  10 
  11 def load_drivers(group: str) -> Dict[str, Any]:
  12     """
  13     Load available drivers for a given group name.
  14 
  15     Gracefully handles:
  16 
  17      - Driver module not able to be imported
  18      - Driver init function throwing an exception or returning None
  19 
  20      By having driver entry_points pointing to a function, we defer loading the driver
  21      module or running any code until required.
  22 
  23     :param group: Name of the entry point group e.g. "datacube.plugins.io.read"
  24 
  25     :returns: Dictionary String -> Driver Object
  26     """
  27 
  28     def safe_load(ep):
  29         from pkg_resources import DistributionNotFound
  30         # pylint: disable=broad-except,bare-except
  31         try:
  32             driver_init = ep.load()
  33         except DistributionNotFound:
  34             # This happens when entry points were marked with extra features,
  35             # but extra feature were not requested for installation
  36             return None
  37         except Exception as e:
  38             _LOG.warning('Failed to resolve driver %s::%s', group, ep.name)
  39             _LOG.warning('Error was: %s', repr(e))
  40             return None
  41 
  42         try:
  43             driver = driver_init()
  44         except Exception:
  45             _LOG.warning('Exception during driver init, driver name: %s::%s', group, ep.name)
  46             return None
  47 
  48         if driver is None:
  49             _LOG.warning('Driver init returned None, driver name: %s::%s', group, ep.name)
  50 
  51         return driver
  52 
  53     def resolve_all(group: str) -> Iterable[Tuple[str, Any]]:
  54         from pkg_resources import iter_entry_points
  55         for ep in iter_entry_points(group=group, name=None):
  56             driver = safe_load(ep)
  57             if driver is not None:
  58                 yield (ep.name, driver)
  59 
  60     return dict((name, driver) for name, driver in resolve_all(group))
  61
  ```
  
  Path: `docs/click_utils.py`
  Content:
  ```
  1 # This file is part of the Open Data Cube, see https://opendatacube.org for more information
  2 #
  3 # Copyright (c) 2015-2023 ODC Contributors
  4 # SPDX-License-Identifier: Apache-2.0
  5 import pkg_resources
  6 from docutils.nodes import literal_block, section, title, make_id
  7 from sphinx.domains import Domain
  8 from docutils.parsers.rst import Directive
  9 import importlib
  10 
  11 import click
  12 
  13 
  14 class ClickHelpDirective(Directive):
  15     has_content = True
  16     required_arguments = 1
  17 
  18     def run(self):
  19         root_cmd = self.arguments[0]
  20 
  21         env = self.state.document.settings.env
  22 
  23         group = find_script_callable_from_env(root_cmd, env)
  24 
  25         return [generate_help_text(group, [root_cmd])]
  26 
  27 
  28 def find_script_callable_from_env(name, env):
  29     commands = env.config.click_utils_commands
  30 
  31     module, function_name = commands[name].split(':')
  32     module = importlib.import_module(module)
  33     return getattr(module, function_name)
  34 
  35 
  36 def find_script_callable(name):
  37     return list(pkg_resources.iter_entry_points(
  38         'console_scripts', name))[0].load()
  39 
  40 
  41 def generate_help_text(command, prefix):
  42     ctx = click.Context(command)
  43     help_opts = command.get_help_option(ctx).opts
  44     full_cmd = ' '.join(prefix)
  45     block = section(None,
  46                     title(None, full_cmd),
  47                     ids=[make_id(full_cmd)], names=[full_cmd])
  48     if help_opts:
  49         h = "$ {} {}\n".format(full_cmd, help_opts[0]) + command.get_help(ctx)
  50         block.append(literal_block(None, h, language='console'))
  51 
  52     if isinstance(command, click.core.MultiCommand):
  53         for c in command.list_commands(ctx):
  54             c = command.resolve_command(ctx, [c])[1]
  55             block.append(generate_help_text(c, prefix+[c.name]))
  56 
  57     return block
  58 
  59 
  60 def make_block(command, opt, content):
  61     h = "$ {} {}\n".format(command, opt) + content
  62     return section(None,
  63                    title(None, command),
  64                    literal_block(None, h, language='console'),
  65                    ids=[make_id(command)], names=[command])
  66 
  67 
  68 class DatacubeDomain(Domain):
  69     name = 'datacube'
  70     label = 'Data Cube'
  71     directives = {
  72         'click-help': ClickHelpDirective,
  73     }
  74 
  75 
  76 def setup(app):
  77     app.add_config_value('click_utils_commands', {}, 'html')
  78 
  79     app.add_domain(DatacubeDomain)
  80     return {
  81         'parallel_read_safe': False,
  82         'parallel_write_safe': False,
  83     }
  84
  ```
  --- 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/datacube/drivers/driver_cache.py b/datacube/drivers/driver_cache.py
  --- a/datacube/drivers/driver_cache.py
  +++ b/datacube/drivers/driver_cache.py
  @@ -26,14 +26,9 @@
       """
   
       def safe_load(ep):
  -        from pkg_resources import DistributionNotFound
           # pylint: disable=broad-except,bare-except
           try:
               driver_init = ep.load()
  -        except DistributionNotFound:
  -            # This happens when entry points were marked with extra features,
  -            # but extra feature were not requested for installation
  -            return None
           except Exception as e:
               _LOG.warning('Failed to resolve driver %s::%s', group, ep.name)
               _LOG.warning('Error was: %s', repr(e))
  @@ -51,8 +46,8 @@
           return driver
   
       def resolve_all(group: str) -> Iterable[Tuple[str, Any]]:
  -        from pkg_resources import iter_entry_points
  -        for ep in iter_entry_points(group=group, name=None):
  +        from importlib.metadata import entry_points
  +        for ep in entry_points(group=group):
               driver = safe_load(ep)
               if driver is not None:
                   yield (ep.name, driver)
  diff --git a/docs/click_utils.py b/docs/click_utils.py
  --- a/docs/click_utils.py
  +++ b/docs/click_utils.py
  @@ -2,7 +2,7 @@
   #
   # Copyright (c) 2015-2023 ODC Contributors
   # SPDX-License-Identifier: Apache-2.0
  -import pkg_resources
  +from importlib.metadata import entry_points
   from docutils.nodes import literal_block, section, title, make_id
   from sphinx.domains import Domain
   from docutils.parsers.rst import Directive
  @@ -34,8 +34,8 @@
   
   
   def find_script_callable(name):
  -    return list(pkg_resources.iter_entry_points(
  -        'console_scripts', name))[0].load()
  +    return list(entry_points(
  +        group='console_scripts', name=name))[0].load()
   
   
   def generate_help_text(command, prefix):
  
verification_info: {"golden_diff": "diff --git a/datacube/drivers/driver_cache.py b/datacube/drivers/driver_cache.py\n--- a/datacube/drivers/driver_cache.py\n+++ b/datacube/drivers/driver_cache.py\n@@ -26,14 +26,9 @@\n     \"\"\"\n \n     def safe_load(ep):\n-        from pkg_resources import DistributionNotFound\n         # pylint: disable=broad-except,bare-except\n         try:\n             driver_init = ep.load()\n-        except DistributionNotFound:\n-            # This happens when entry points were marked with extra features,\n-            # but extra feature were not requested for installation\n-            return None\n         except Exception as e:\n             _LOG.warning('Failed to resolve driver %s::%s', group, ep.name)\n             _LOG.warning('Error was: %s', repr(e))\n@@ -51,8 +46,8 @@\n         return driver\n \n     def resolve_all(group: str) -> Iterable[Tuple[str, Any]]:\n-        from pkg_resources import iter_entry_points\n-        for ep in iter_entry_points(group=group, name=None):\n+        from importlib.metadata import entry_points\n+        for ep in entry_points(group=group):\n             driver = safe_load(ep)\n             if driver is not None:\n                 yield (ep.name, driver)\ndiff --git a/docs/click_utils.py b/docs/click_utils.py\n--- a/docs/click_utils.py\n+++ b/docs/click_utils.py\n@@ -2,7 +2,7 @@\n #\n # Copyright (c) 2015-2023 ODC Contributors\n # SPDX-License-Identifier: Apache-2.0\n-import pkg_resources\n+from importlib.metadata import entry_points\n from docutils.nodes import literal_block, section, title, make_id\n from sphinx.domains import Domain\n from docutils.parsers.rst import Directive\n@@ -34,8 +34,8 @@\n \n \n def find_script_callable(name):\n-    return list(pkg_resources.iter_entry_points(\n-        'console_scripts', name))[0].load()\n+    return list(entry_points(\n+        group='console_scripts', name=name))[0].load()\n \n \n def generate_help_text(command, prefix):\n", "issue": "DeprecationWarning on `pkg_resources` in Python 3.10\n### Expected behaviour\r\nODC running in Python 3.10 shouldn't print `DeprecationWarning`s.\r\n\r\n### Actual behaviour\r\n\r\nWhen running some ODC code:\r\n```\r\n  .../testenv/lib/python3.10/site-packages/datacube/drivers/driver_cache.py:54: DeprecationWarning: pkg_resources is deprecated as an API\r\n    from pkg_resources import iter_entry_points\r\n```\r\nWhich is: https://github.com/opendatacube/datacube-core/blob/develop/datacube/drivers/driver_cache.py#L29\r\n\r\nThis code should be replaced with modules from the Python standard library, see: [Package Discovery and Resource Access using pkg_resources - setuptools 68.0.0.post20230621 documentation](https://setuptools.pypa.io/en/latest/pkg_resources.html) and [importlib.resources \u2013 Resources \u2014 Python 3.11.4 documentation](https://docs.python.org/3/library/importlib.resources.html#module-importlib.resources).\r\n\r\nWe've already set the minimum Python version as 3.8, and the stdlib modules exist since 3.7, so we don't need to add the external backports as dependencies.\r\n\r\n### Environment information\r\n\r\n* Which ``datacube --version`` are you using?\r\n   `Open Data Cube core, version 1.8.13`\r\n* What datacube deployment/enviornment are you running against?\r\n   Local installation from conda-forge.\r\n\r\n\n", "before_files": [{"content": "# This file is part of the Open Data Cube, see https://opendatacube.org for more information\n#\n# Copyright (c) 2015-2023 ODC Contributors\n# SPDX-License-Identifier: Apache-2.0\nimport logging\nfrom typing import Dict, Any, Tuple, Iterable\n\n_LOG = logging.getLogger(__name__)\n\n\ndef load_drivers(group: str) -> Dict[str, Any]:\n    \"\"\"\n    Load available drivers for a given group name.\n\n    Gracefully handles:\n\n     - Driver module not able to be imported\n     - Driver init function throwing an exception or returning None\n\n     By having driver entry_points pointing to a function, we defer loading the driver\n     module or running any code until required.\n\n    :param group: Name of the entry point group e.g. \"datacube.plugins.io.read\"\n\n    :returns: Dictionary String -> Driver Object\n    \"\"\"\n\n    def safe_load(ep):\n        from pkg_resources import DistributionNotFound\n        # pylint: disable=broad-except,bare-except\n        try:\n            driver_init = ep.load()\n        except DistributionNotFound:\n            # This happens when entry points were marked with extra features,\n            # but extra feature were not requested for installation\n            return None\n        except Exception as e:\n            _LOG.warning('Failed to resolve driver %s::%s', group, ep.name)\n            _LOG.warning('Error was: %s', repr(e))\n            return None\n\n        try:\n            driver = driver_init()\n        except Exception:\n            _LOG.warning('Exception during driver init, driver name: %s::%s', group, ep.name)\n            return None\n\n        if driver is None:\n            _LOG.warning('Driver init returned None, driver name: %s::%s', group, ep.name)\n\n        return driver\n\n    def resolve_all(group: str) -> Iterable[Tuple[str, Any]]:\n        from pkg_resources import iter_entry_points\n        for ep in iter_entry_points(group=group, name=None):\n            driver = safe_load(ep)\n            if driver is not None:\n                yield (ep.name, driver)\n\n    return dict((name, driver) for name, driver in resolve_all(group))\n", "path": "datacube/drivers/driver_cache.py"}, {"content": "# This file is part of the Open Data Cube, see https://opendatacube.org for more information\n#\n# Copyright (c) 2015-2023 ODC Contributors\n# SPDX-License-Identifier: Apache-2.0\nimport pkg_resources\nfrom docutils.nodes import literal_block, section, title, make_id\nfrom sphinx.domains import Domain\nfrom docutils.parsers.rst import Directive\nimport importlib\n\nimport click\n\n\nclass ClickHelpDirective(Directive):\n    has_content = True\n    required_arguments = 1\n\n    def run(self):\n        root_cmd = self.arguments[0]\n\n        env = self.state.document.settings.env\n\n        group = find_script_callable_from_env(root_cmd, env)\n\n        return [generate_help_text(group, [root_cmd])]\n\n\ndef find_script_callable_from_env(name, env):\n    commands = env.config.click_utils_commands\n\n    module, function_name = commands[name].split(':')\n    module = importlib.import_module(module)\n    return getattr(module, function_name)\n\n\ndef find_script_callable(name):\n    return list(pkg_resources.iter_entry_points(\n        'console_scripts', name))[0].load()\n\n\ndef generate_help_text(command, prefix):\n    ctx = click.Context(command)\n    help_opts = command.get_help_option(ctx).opts\n    full_cmd = ' '.join(prefix)\n    block = section(None,\n                    title(None, full_cmd),\n                    ids=[make_id(full_cmd)], names=[full_cmd])\n    if help_opts:\n        h = \"$ {} {}\\n\".format(full_cmd, help_opts[0]) + command.get_help(ctx)\n        block.append(literal_block(None, h, language='console'))\n\n    if isinstance(command, click.core.MultiCommand):\n        for c in command.list_commands(ctx):\n            c = command.resolve_command(ctx, [c])[1]\n            block.append(generate_help_text(c, prefix+[c.name]))\n\n    return block\n\n\ndef make_block(command, opt, content):\n    h = \"$ {} {}\\n\".format(command, opt) + content\n    return section(None,\n                   title(None, command),\n                   literal_block(None, h, language='console'),\n                   ids=[make_id(command)], names=[command])\n\n\nclass DatacubeDomain(Domain):\n    name = 'datacube'\n    label = 'Data Cube'\n    directives = {\n        'click-help': ClickHelpDirective,\n    }\n\n\ndef setup(app):\n    app.add_config_value('click_utils_commands', {}, 'html')\n\n    app.add_domain(DatacubeDomain)\n    return {\n        'parallel_read_safe': False,\n        'parallel_write_safe': False,\n    }\n", "path": "docs/click_utils.py"}], "after_files": [{"content": "# This file is part of the Open Data Cube, see https://opendatacube.org for more information\n#\n# Copyright (c) 2015-2023 ODC Contributors\n# SPDX-License-Identifier: Apache-2.0\nimport logging\nfrom typing import Dict, Any, Tuple, Iterable\n\n_LOG = logging.getLogger(__name__)\n\n\ndef load_drivers(group: str) -> Dict[str, Any]:\n    \"\"\"\n    Load available drivers for a given group name.\n\n    Gracefully handles:\n\n     - Driver module not able to be imported\n     - Driver init function throwing an exception or returning None\n\n     By having driver entry_points pointing to a function, we defer loading the driver\n     module or running any code until required.\n\n    :param group: Name of the entry point group e.g. \"datacube.plugins.io.read\"\n\n    :returns: Dictionary String -> Driver Object\n    \"\"\"\n\n    def safe_load(ep):\n        # pylint: disable=broad-except,bare-except\n        try:\n            driver_init = ep.load()\n        except Exception as e:\n            _LOG.warning('Failed to resolve driver %s::%s', group, ep.name)\n            _LOG.warning('Error was: %s', repr(e))\n            return None\n\n        try:\n            driver = driver_init()\n        except Exception:\n            _LOG.warning('Exception during driver init, driver name: %s::%s', group, ep.name)\n            return None\n\n        if driver is None:\n            _LOG.warning('Driver init returned None, driver name: %s::%s', group, ep.name)\n\n        return driver\n\n    def resolve_all(group: str) -> Iterable[Tuple[str, Any]]:\n        from importlib.metadata import entry_points\n        for ep in entry_points(group=group):\n            driver = safe_load(ep)\n            if driver is not None:\n                yield (ep.name, driver)\n\n    return dict((name, driver) for name, driver in resolve_all(group))\n", "path": "datacube/drivers/driver_cache.py"}, {"content": "# This file is part of the Open Data Cube, see https://opendatacube.org for more information\n#\n# Copyright (c) 2015-2023 ODC Contributors\n# SPDX-License-Identifier: Apache-2.0\nfrom importlib.metadata import entry_points\nfrom docutils.nodes import literal_block, section, title, make_id\nfrom sphinx.domains import Domain\nfrom docutils.parsers.rst import Directive\nimport importlib\n\nimport click\n\n\nclass ClickHelpDirective(Directive):\n    has_content = True\n    required_arguments = 1\n\n    def run(self):\n        root_cmd = self.arguments[0]\n\n        env = self.state.document.settings.env\n\n        group = find_script_callable_from_env(root_cmd, env)\n\n        return [generate_help_text(group, [root_cmd])]\n\n\ndef find_script_callable_from_env(name, env):\n    commands = env.config.click_utils_commands\n\n    module, function_name = commands[name].split(':')\n    module = importlib.import_module(module)\n    return getattr(module, function_name)\n\n\ndef find_script_callable(name):\n    return list(entry_points(\n        group='console_scripts', name=name))[0].load()\n\n\ndef generate_help_text(command, prefix):\n    ctx = click.Context(command)\n    help_opts = command.get_help_option(ctx).opts\n    full_cmd = ' '.join(prefix)\n    block = section(None,\n                    title(None, full_cmd),\n                    ids=[make_id(full_cmd)], names=[full_cmd])\n    if help_opts:\n        h = \"$ {} {}\\n\".format(full_cmd, help_opts[0]) + command.get_help(ctx)\n        block.append(literal_block(None, h, language='console'))\n\n    if isinstance(command, click.core.MultiCommand):\n        for c in command.list_commands(ctx):\n            c = command.resolve_command(ctx, [c])[1]\n            block.append(generate_help_text(c, prefix+[c.name]))\n\n    return block\n\n\ndef make_block(command, opt, content):\n    h = \"$ {} {}\\n\".format(command, opt) + content\n    return section(None,\n                   title(None, command),\n                   literal_block(None, h, language='console'),\n                   ids=[make_id(command)], names=[command])\n\n\nclass DatacubeDomain(Domain):\n    name = 'datacube'\n    label = 'Data Cube'\n    directives = {\n        'click-help': ClickHelpDirective,\n    }\n\n\ndef setup(app):\n    app.add_config_value('click_utils_commands', {}, 'html')\n\n    app.add_domain(DatacubeDomain)\n    return {\n        'parallel_read_safe': False,\n        'parallel_write_safe': False,\n    }\n", "path": "docs/click_utils.py"}]}