Skip to content

Commit cff398a

Browse files
Merge pull request #53 from josh-ashkinaze/dev/pkg_resources_change
(refactor) add support for both pkg_resources and importlib
2 parents 28dfd8a + 9b5764e commit cff398a

File tree

2 files changed

+61
-4
lines changed

2 files changed

+61
-4
lines changed

plurals/helpers.py

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from typing import List, Dict, Any
44

55
import pandas as pd
6-
import pkg_resources
76
import yaml
87

98

@@ -28,8 +27,7 @@ def print_anes_mapping():
2827
2928
"""
3029
mapping = load_yaml('anes-mapping.yaml')
31-
df = pd.read_csv(pkg_resources.resource_filename(
32-
__name__, 'data/anes_pilot_2024_20240319.csv'))
30+
df = pd.read_csv(get_resource_path(__name__, 'data/anes_pilot_2024_20240319.csv'))
3331
for key in mapping.keys():
3432
details = mapping[key]
3533

@@ -79,7 +77,7 @@ def load_yaml(file_path: str) -> Dict[str, Any]:
7977
Returns:
8078
A dictionary containing the contents of the YAML file.
8179
"""
82-
full_path = pkg_resources.resource_filename(__name__, file_path)
80+
full_path = get_resource_path(__name__, file_path)
8381
if not os.path.exists(full_path):
8482
raise FileNotFoundError(
8583
f"The file {full_path} does not exist. Please ensure the file path is correct.")
@@ -219,3 +217,35 @@ def format(self, avoid_double_period=True, **kwargs):
219217
f"{value}.", value)
220218

221219
return formatted_string
220+
221+
222+
def get_resource_path(package: str, resource: str) -> str:
223+
"""
224+
Get the path to a resource file, supporting both pkg_resources and importlib.resources.
225+
Falls back to importlib.resources if pkg_resources is not available.
226+
227+
Problem this solves:
228+
- In python 3.12, pkg_resources is being deprecated in favor of importlib.resources, and
229+
it no longer comes with pkg_resources. This creates an import error unless user does `pip install setuptools` but it is
230+
bad practice to add setuptools as a runtime dependency.
231+
232+
- If I just switch to importlib, this is limiting since importlib is only for 3.9+.
233+
234+
- So the solution is to use pkg_resources if available, and if not, use importlib.resources.
235+
236+
237+
Args:
238+
package: The package name (just __name__ usually)
239+
resource: The resource path relative to the package
240+
241+
Returns:
242+
str: The full path to the resource
243+
"""
244+
try:
245+
import pkg_resources
246+
return pkg_resources.resource_filename(package, resource)
247+
except ImportError:
248+
from importlib import resources
249+
root_package = package.split('.')[0]
250+
with resources.path(root_package, resource) as path:
251+
return str(path)

plurals/tests.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2087,5 +2087,32 @@ def test_structure_repr_with_empty_collections(self):
20872087
print(repr_string)
20882088
self.assertIn("'responses': []", repr_string)
20892089

2090+
2091+
from pathlib import Path
2092+
2093+
2094+
class TestPathHandling(unittest.TestCase):
2095+
"""Test cases for resource path handling."""
2096+
2097+
def test_load_yaml_pkg_resources_paths(self):
2098+
"""Test load_yaml works both with and without pkg_resources."""
2099+
2100+
# test we can load stuff with pkg_resources
2101+
yaml_content_pkg_resources = load_yaml("instructions.yaml")
2102+
self.assertIsInstance(yaml_content_pkg_resources, dict)
2103+
self.assertIn("persona_template", yaml_content_pkg_resources)
2104+
self.assertIn("combination_instructions", yaml_content_pkg_resources)
2105+
2106+
# test we can load stuff without pkg_resources
2107+
with patch("pkg_resources.resource_filename", side_effect=ImportError):
2108+
yaml_content_pathlib = load_yaml("instructions.yaml")
2109+
self.assertIsInstance(yaml_content_pathlib, dict)
2110+
self.assertIn("persona_template", yaml_content_pathlib)
2111+
self.assertIn("combination_instructions", yaml_content_pathlib)
2112+
2113+
# assert equality of the two methods
2114+
self.assertEqual(yaml_content_pkg_resources, yaml_content_pathlib)
2115+
2116+
20902117
if __name__ == "__main__":
20912118
unittest.main()

0 commit comments

Comments
 (0)