Skip to content

Commit f7e18d2

Browse files
committed
fix: remove pkg_resources dependency on python 3
Fixes #232 Signed-off-by: Martin Styk <mart.styk@gmail.com>
1 parent d0104d0 commit f7e18d2

8 files changed

Lines changed: 144 additions & 15 deletions

File tree

Client/src/bkr/__init__.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
2-
try:
3-
__import__('pkg_resources').declare_namespace(__name__)
4-
except ImportError:
2+
import sys
3+
if sys.version_info[0] >= 3:
54
from pkgutil import extend_path
65
__path__ = extend_path(__path__, __name__)
6+
else:
7+
try:
8+
__import__('pkg_resources').declare_namespace(__name__)
9+
except ImportError:
10+
from pkgutil import extend_path
11+
__path__ = extend_path(__path__, __name__)

Client/src/bkr/client/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@
1414
import xml.dom.minidom
1515
from optparse import OptionGroup
1616

17-
import pkg_resources
1817
from six.moves.urllib_parse import urljoin
1918

19+
from bkr.common.resources import resource_filename
20+
2021
from bkr.client.command import Command
2122
from bkr.common.pyconfig import PyConfigParser
2223

@@ -53,7 +54,7 @@ def host_filter_presets():
5354

5455
_host_filter_presets = {}
5556
config_files = (
56-
sorted(glob.glob(pkg_resources.resource_filename('bkr.client', 'host-filters/*.conf')))
57+
sorted(glob.glob(resource_filename('bkr.client', 'host-filters/*.conf')))
5758
+ sorted(glob.glob('/etc/beaker/host-filters/*.conf')))
5859
user_config_file = os.path.expanduser('~/.beaker_client/host-filter')
5960
if os.path.exists(user_config_file):

Client/src/bkr/client/commands/cmd_job_submit.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,10 @@
106106
import xml.dom.minidom
107107

108108
import lxml.etree
109-
import pkg_resources
110109
import six
111110

111+
from bkr.common.resources import resource_stream
112+
112113
from bkr.client import BeakerCommand
113114
from bkr.client.convert import Convert
114115
from bkr.client.task_watcher import *
@@ -211,7 +212,7 @@ def run(self, *args, **kwargs):
211212
if not jobs:
212213
jobs = ['-'] # read one job from stdin by default
213214
job_schema = lxml.etree.RelaxNG(lxml.etree.parse(
214-
pkg_resources.resource_stream('bkr.common', 'schema/beaker-job.rng')))
215+
resource_stream('bkr.common', 'schema/beaker-job.rng')))
215216

216217
self.set_hub(**kwargs)
217218
submitted_jobs = []

Client/src/bkr/client/main.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@
1414
from optparse import SUPPRESS_HELP
1515

1616
import gssapi
17-
import pkg_resources
1817
from six.moves.xmlrpc_client import Fault
1918

19+
from bkr.common.resources import iter_entry_points
20+
2021
from bkr.client.command import BeakerClientConfigurationError
2122
from bkr.client.command import ClientCommandContainer
2223
from bkr.client.command import CommandOptionParser
@@ -41,7 +42,7 @@ def register_all(cls):
4142
# Load subcommands from setuptools entry points in the bkr.client.commands
4243
# group. This is the new, preferred way for other packages to provide their
4344
# own bkr subcommands.
44-
for entrypoint in pkg_resources.iter_entry_points('bkr.client.commands'):
45+
for entrypoint in iter_entry_points('bkr.client.commands'):
4546
cls.register_plugin(entrypoint.load(), name=entrypoint.name)
4647

4748

Common/bkr/__init__.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
2-
try:
3-
__import__('pkg_resources').declare_namespace(__name__)
4-
except ImportError:
2+
import sys
3+
if sys.version_info[0] >= 3:
54
from pkgutil import extend_path
65
__path__ = extend_path(__path__, __name__)
6+
else:
7+
try:
8+
__import__('pkg_resources').declare_namespace(__name__)
9+
except ImportError:
10+
from pkgutil import extend_path
11+
__path__ = extend_path(__path__, __name__)

Common/bkr/common/resources.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Copyright Contributors to the Beaker project.
2+
# SPDX-License-Identifier: GPL-2.0-or-later
3+
4+
import sys
5+
6+
if sys.version_info[0] == 3 and sys.version_info < (3, 9):
7+
raise ImportError("Python 3.9+ is required; found %d.%d" % sys.version_info[:2])
8+
9+
if sys.version_info >= (3, 9):
10+
import importlib.resources
11+
import importlib.metadata
12+
13+
def resource_stream(package, resource_name):
14+
return importlib.resources.files(package).joinpath(resource_name).open("rb")
15+
16+
def resource_filename(package, resource_name):
17+
return str(importlib.resources.files(package).joinpath(resource_name))
18+
19+
def resource_string(package, resource_name):
20+
return importlib.resources.files(package).joinpath(resource_name).read_bytes()
21+
22+
def resource_listdir(package, resource_name):
23+
return [
24+
item.name
25+
for item in importlib.resources.files(package)
26+
.joinpath(resource_name)
27+
.iterdir()
28+
]
29+
30+
def resource_exists(package, resource_name):
31+
traversable = importlib.resources.files(package).joinpath(resource_name)
32+
return traversable.is_file() or traversable.is_dir()
33+
34+
def iter_entry_points(group):
35+
return importlib.metadata.entry_points(group=group)
36+
37+
else:
38+
from pkg_resources import (
39+
resource_stream,
40+
resource_filename,
41+
resource_string,
42+
resource_listdir,
43+
resource_exists,
44+
iter_entry_points,
45+
)
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Copyright Contributors to the Beaker project.
2+
# SPDX-License-Identifier: GPL-2.0-or-later
3+
4+
import unittest
5+
6+
from bkr.common.resources import (
7+
resource_stream,
8+
resource_filename,
9+
resource_string,
10+
resource_listdir,
11+
resource_exists,
12+
iter_entry_points,
13+
)
14+
15+
16+
class ResourceStreamTest(unittest.TestCase):
17+
def test_resource_stream_returns_readable_file_object(self):
18+
f = resource_stream("bkr.common", "schema/beaker-job.rng")
19+
try:
20+
data = f.read()
21+
self.assertIsInstance(data, bytes)
22+
self.assertGreater(len(data), 0)
23+
self.assertIn(b"<grammar", data)
24+
finally:
25+
f.close()
26+
27+
28+
class ResourceFilenameTest(unittest.TestCase):
29+
def test_resource_filename_returns_valid_path(self):
30+
import os
31+
32+
path = resource_filename("bkr.common", "schema/beaker-job.rng")
33+
self.assertIsInstance(path, str)
34+
self.assertTrue(os.path.isfile(path), "Path does not exist: %s" % path)
35+
36+
37+
class ResourceStringTest(unittest.TestCase):
38+
def test_resource_string_returns_bytes(self):
39+
data = resource_string("bkr.common", "schema/beaker-job.rng")
40+
self.assertIsInstance(data, bytes)
41+
self.assertGreater(len(data), 0)
42+
self.assertIn(b"<grammar", data)
43+
44+
45+
class ResourceListdirTest(unittest.TestCase):
46+
def test_resource_listdir_returns_list(self):
47+
entries = resource_listdir("bkr.common", "schema")
48+
self.assertIsInstance(entries, list)
49+
self.assertIn("beaker-job.rng", entries)
50+
self.assertIn("beaker-task.rng", entries)
51+
52+
53+
class ResourceExistsTest(unittest.TestCase):
54+
def test_resource_exists_true(self):
55+
self.assertTrue(resource_exists("bkr.common", "schema/beaker-job.rng"))
56+
57+
def test_resource_exists_false(self):
58+
self.assertFalse(resource_exists("bkr.common", "schema/nonexistent.xyz"))
59+
60+
61+
class IterEntryPointsTest(unittest.TestCase):
62+
def test_iter_entry_points_returns_iterable(self):
63+
eps = iter_entry_points("console_scripts")
64+
result = list(eps)
65+
self.assertIsInstance(result, list)
66+
67+
def test_iter_entry_points_empty_group(self):
68+
eps = iter_entry_points("nonexistent.group.12345")
69+
result = list(eps)
70+
self.assertEqual(result, [])

Common/bkr/common/test_schema.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55
# (at your option) any later version.
66

77
import unittest
8-
import pkg_resources
98
import lxml.etree
109

10+
from bkr.common.resources import resource_stream
11+
1112
class SchemaTestBase(unittest.TestCase):
1213

1314
schema_doc = None # filled by setUpClass
@@ -26,7 +27,7 @@ class TaskSchemaTest(SchemaTestBase):
2627

2728
@classmethod
2829
def setUpClass(cls):
29-
cls.schema_doc = lxml.etree.parse(pkg_resources.resource_stream(
30+
cls.schema_doc = lxml.etree.parse(resource_stream(
3031
'bkr.common', 'schema/beaker-task.rng'))
3132

3233
def test_minimal_task(self):
@@ -86,7 +87,7 @@ class JobSchemaTest(SchemaTestBase):
8687

8788
@classmethod
8889
def setUpClass(cls):
89-
cls.schema_doc = lxml.etree.parse(pkg_resources.resource_stream(
90+
cls.schema_doc = lxml.etree.parse(resource_stream(
9091
'bkr.common', 'schema/beaker-job.rng'))
9192

9293
def test_minimal_job(self):

0 commit comments

Comments
 (0)