Skip to content

Commit a4d08b5

Browse files
committed
refactor(config): replace deprecated pkg_resources (#503)
Replace `pkg_resources`` with the modern `importlib.resources` API to resolve deprecation warnings. Uses `importlib.resources`` for Python 3.9+ and the `importlib_resources` backport for Python 3.8 compatibility. Closes #502
1 parent cbdd7ab commit a4d08b5

File tree

4 files changed

+60
-16
lines changed

4 files changed

+60
-16
lines changed

reana_commons/api_client.py

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,17 @@
1010
import json
1111
import logging
1212
import os
13+
import sys
1314
import traceback
1415
from typing import Optional
1516

16-
import pkg_resources
1717
from bravado.client import RequestsClient, SwaggerClient
18+
19+
# Use importlib.resources for Python 3.9+ or importlib_resources backport for 3.8
20+
if sys.version_info >= (3, 9):
21+
from importlib.resources import files
22+
else:
23+
from importlib_resources import files
1824
from bravado.exception import (
1925
HTTPBadRequest,
2026
HTTPError,
@@ -74,13 +80,17 @@ def _load_config_from_env(self):
7480

7581
def _get_spec(self, spec_file):
7682
"""Get json specification from package data."""
77-
spec_file_path = os.path.join(
78-
pkg_resources.resource_filename("reana_commons", "openapi_specifications"),
79-
spec_file,
80-
)
81-
82-
with open(spec_file_path) as f:
83-
json_spec = json.load(f)
83+
# Get the OpenAPI specification file using importlib.resources
84+
package_files = files("reana_commons")
85+
spec_resource = package_files / "openapi_specifications" / spec_file
86+
87+
# For Python 3.9+, we need to handle this as a Traversable
88+
if sys.version_info >= (3, 9):
89+
json_spec = json.loads(spec_resource.read_text())
90+
else:
91+
# For Python 3.8 with backport, convert to string path
92+
with open(str(spec_resource)) as f:
93+
json_spec = json.load(f)
8494
return json_spec
8595

8696

reana_commons/config.py

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,18 @@
1111
import json
1212
import logging
1313
import os
14+
import sys
1415

15-
import pkg_resources
1616
import yaml
1717

1818
from reana_commons.errors import REANAConfigDoesNotExist
1919

20+
# Use importlib.resources for Python 3.9+ or importlib_resources backport for 3.8
21+
if sys.version_info >= (3, 9):
22+
from importlib.resources import files
23+
else:
24+
from importlib_resources import files
25+
2026

2127
class REANAConfig:
2228
"""REANA global configuration class."""
@@ -40,9 +46,30 @@ def load(cls, kind):
4046
return cls._read_file(cls.config_mapping[kind])
4147

4248

43-
reana_yaml_schema_file_path = pkg_resources.resource_filename(
44-
__name__, "validation/schemas/reana_analysis_schema.json"
45-
)
49+
def _get_reana_yaml_schema_file_path():
50+
"""Get the path to the REANA YAML schema file.
51+
52+
This function handles the differences between Python versions and ensures
53+
the schema file is accessible as a real filesystem path.
54+
"""
55+
package_files = files("reana_commons")
56+
schema_resource = (
57+
package_files / "validation" / "schemas" / "reana_analysis_schema.json"
58+
)
59+
60+
# For Python 3.8 with backport, we can directly convert to string
61+
# For Python 3.9+, the resource might be in a zip, so we need to check
62+
if hasattr(schema_resource, "is_file") and schema_resource.is_file():
63+
# It's a real file on the filesystem
64+
return str(schema_resource)
65+
else:
66+
# For older importlib_resources or when in a zip, try direct string conversion
67+
# This should work for the backport
68+
return str(schema_resource)
69+
70+
71+
# Get the path to the validation schema file
72+
reana_yaml_schema_file_path = _get_reana_yaml_schema_file_path()
4673
"""REANA specification schema location."""
4774

4875
REANA_COMPONENT_PREFIX = os.getenv("REANA_COMPONENT_PREFIX", "reana")

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
"checksumdir>=1.1.4,<1.2",
6262
"click>=7.0",
6363
"fs>=2.0",
64+
"importlib_resources>=5.0; python_version<'3.9'",
6465
"jsonschema[format]>=3.0.1",
6566
"kombu>=4.6",
6667
"mock>=3.0,<4",

tests/test_utils.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@
1010

1111
import os
1212
import shutil
13+
import sys
1314
import time
1415
from hashlib import md5
1516

16-
import pkg_resources
1717
import pytest
1818
from pytest_reana.fixtures import sample_workflow_workspace
1919

20+
2021
from reana_commons.utils import (
2122
calculate_file_access_time,
2223
calculate_hash_of_dir,
@@ -70,9 +71,14 @@ def test_calculate_hash_of_dir(sample_workflow_workspace): # noqa: F811
7071
non_existing_dir_hash = calculate_hash_of_dir("a/b/c")
7172
assert non_existing_dir_hash == -1
7273

73-
test_workspace_path = pkg_resources.resource_filename(
74-
"pytest_reana", "test_workspace"
75-
)
74+
# Get the path to the test workspace by finding the pytest_reana package location
75+
import pytest_reana
76+
import pathlib
77+
78+
# Get the package path and construct test_workspace path
79+
package_path = pathlib.Path(pytest_reana.__file__).parent
80+
test_workspace_path = package_path / "test_workspace"
81+
7682
sample_workflow_workspace_path = next(sample_workflow_workspace("sample"))
7783
shutil.rmtree(sample_workflow_workspace_path)
7884
shutil.copytree(test_workspace_path, sample_workflow_workspace_path)

0 commit comments

Comments
 (0)