From dcfe856b23ffbe3220aac6c7764cea1d976f9586 Mon Sep 17 00:00:00 2001 From: rchaput Date: Mon, 15 Jul 2024 14:20:16 +0200 Subject: [PATCH] Improve the `find_profile_data` function for Python3.9+ The `importlib.resources` lib that we use in this function has changed its API. Our function would still work but raise a deprecation warning. There is a risk that the functions we require would be deleted at some point; this commit makes our function future-proof (at least for the next versions). We try to import the most recent functions; if it does not work, we assume we are on an older version and resort to the previous API (for which there will be no deprecation warning at this point). Python 3.7 is no longer supported by the Python community; Python 3.8 will reach end-of-life on 2024-10. At some point, our function could drop this "backup" import for older versions; but for now, they may still be used. --- smartgrid/make_env.py | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/smartgrid/make_env.py b/smartgrid/make_env.py index 35dd0be..08b2e95 100644 --- a/smartgrid/make_env.py +++ b/smartgrid/make_env.py @@ -35,13 +35,6 @@ def find_profile_data(dataset: str, filename: str) -> str: :py:mod:`importlib.resources` is used to get a path to the file through the package. - This function may raise a ``DeprecationWarning`` when accessing - files through the package on Python3.11+. It is due to relying on the - :py:func:`importlib.resources.path` function, which is deprecated since - Python 3.11. As we support up to Python 3.7, and as the function is - only available since Python 3.9, it is still used instead of the more - recent :py:func:`importlib.resources.files`. - :param dataset: The name of the folder containing the desired file, within the ``data`` folder. For example, ``openei`` to access the OpenEI dataset. This dataset cannot be nested, e.g., ``dataset/subdataset`` @@ -61,20 +54,25 @@ def find_profile_data(dataset: str, filename: str) -> str: # Hard mode: need to access it through the package (importlib). # Also, importlib returns a context, so we need to get the path # and exit the context when Python terminates. - import importlib_resources from contextlib import ExitStack import atexit + # Depending on the Python version, there are two ways to use importlib. + try: + # Python 3.9+ + from importlib.resources import files, as_file + data = files('smartgrid.data').joinpath(dataset, filename) + ctx = as_file(data) + except ImportError: + # Python 3.7 and 3.8 + from importlib.resources import path + ctx = path(f'smartgrid.data.{dataset}', filename) # Handle the context file_manager = ExitStack() # Close the context when Python terminates atexit.register(file_manager.close) - # `path` is deprecated since Python3.9, but we support up to 3.7, - # so we still use `path`. There is not much benefit to check whether - # the new `files` API is available and use it instead. - ctx = importlib_resources.path(f'smartgrid.data.{dataset}', filename) - path = file_manager.enter_context(ctx) + data_file_path = file_manager.enter_context(ctx) # Convert the PosixPath to a simple str for easier usage. - return str(path) + return str(data_file_path) def make_basic_smartgrid(