Merge pull request #36044 from openedx/pkg_resources-depr

Replace pkg_resources with importlib.resources
This commit is contained in:
Feanil Patel
2025-01-23 11:05:45 -05:00
committed by GitHub
14 changed files with 48 additions and 62 deletions

View File

@@ -11,7 +11,7 @@ from datetime import datetime
from tempfile import NamedTemporaryFile, mkdtemp
import olxcleaner
import pkg_resources
from importlib.metadata import entry_points
from ccx_keys.locator import CCXLocator
from celery import shared_task
from celery.utils.log import get_task_logger
@@ -85,7 +85,7 @@ LOGGER = get_task_logger(__name__)
FILE_READ_CHUNK = 1024 # bytes
FULL_COURSE_REINDEX_THRESHOLD = 1
ALL_ALLOWED_XBLOCKS = frozenset(
[entry_point.name for entry_point in pkg_resources.iter_entry_points("xblock.v1")]
[entry_point.name for entry_point in entry_points(group="xblock.v1")]
)

View File

@@ -16,10 +16,6 @@ filterwarnings =
ignore:.*You can remove default_app_config.*:PendingDeprecationWarning
# ABC deprecation Warning comes from libsass
ignore:Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated.*:DeprecationWarning:sass
# declare_namespace Warning comes from XBlock https://github.com/openedx/XBlock/issues/641
# and also due to dependency: https://github.com/PyFilesystem/pyfilesystem2
ignore:Deprecated call to `pkg_resources.declare_namespace.*:DeprecationWarning
ignore:.*pkg_resources is deprecated as an API.*:DeprecationWarning
ignore:'etree' is deprecated. Use 'xml.etree.ElementTree' instead.:DeprecationWarning:wiki
norecursedirs = envs

View File

@@ -5,7 +5,8 @@ import contextlib
import hashlib
import os
import pkg_resources
from importlib.resources import files
from pathlib import Path
from django.conf import settings
from mako.exceptions import TopLevelLookupException
from mako.lookup import TemplateLookup
@@ -122,7 +123,7 @@ def add_lookup(namespace, directory, package=None, prepend=False):
"""
Adds a new mako template lookup directory to the given namespace.
If `package` is specified, `pkg_resources` is used to look up the directory
If `package` is specified, `importlib.resources` is used to look up the directory
inside the given package. Otherwise `directory` is assumed to be a path
in the filesystem.
"""
@@ -136,8 +137,11 @@ def add_lookup(namespace, directory, package=None, prepend=False):
encoding_errors='replace',
)
if package:
directory = pkg_resources.resource_filename(package, directory)
templates.add_directory(directory, prepend=prepend)
package, module_path = package.split('.', 1)
module_dir = str(Path(module_path).parent)
directory = files(package).joinpath(module_dir, directory)
templates.add_directory(str(directory), prepend=prepend)
@request_cached()

View File

@@ -15,10 +15,6 @@ filterwarnings =
ignore:.*You can remove default_app_config.*:PendingDeprecationWarning
# ABC deprecation Warning comes from libsass
ignore:Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated.*:DeprecationWarning:sass
# declare_namespace Warning comes from XBlock https://github.com/openedx/XBlock/issues/641
# and also due to dependency: https://github.com/PyFilesystem/pyfilesystem2
ignore:Deprecated call to `pkg_resources.declare_namespace.*:DeprecationWarning
ignore:.*pkg_resources is deprecated as an API.*:DeprecationWarning
ignore:'etree' is deprecated. Use 'xml.etree.ElementTree' instead.:DeprecationWarning:wiki
norecursedirs = .cache

View File

@@ -84,7 +84,7 @@ mechanism:
``openedx.core.lib.xblock_pipeline.finder.XBlockPipelineFinder``
Custom finder that accesses and extracts assets from pip-installed XBlocks via
``pkg_resources``.
``importlib.resources``.
``openedx.core.storage.DevelopmentStorage/ProductionStorage``
Custom ``FileStorage`` classes that mostly exist for theme-awareness.

View File

@@ -305,7 +305,7 @@ be updated to support the new ``XBlockI18nService``
def _get_statici18n_js_url():
"""
Returns the Javascript translation file for the currently selected language, if any found by
`pkg_resources`
`importlib.resources.files`
"""
lang_code = translation.get_language()
if not lang_code:
@@ -320,8 +320,8 @@ be updated to support the new ``XBlockI18nService``
text_js = 'public/js/translations/{lang_code}/text.js'
country_code = lang_code.split('-')[0]
for code in (translation.to_locale(lang_code), lang_code, country_code):
if pkg_resources.resource_exists(loader.module_name, text_js.format(lang_code=code)):
return text_js.format(lang_code=code)
if files(loader.module_name).joinpath(text_js.format(lang_code=code)).is_file():
return text_js.format(lang_code=code)
return None

View File

@@ -144,16 +144,6 @@ def log_python_warnings():
category=DeprecationWarning,
module="sass",
)
warnings.filterwarnings(
'ignore',
'Deprecated call to `pkg_resources.declare_namespace.*',
category=DeprecationWarning,
)
warnings.filterwarnings(
'ignore',
'.*pkg_resources is deprecated as an API.*',
category=DeprecationWarning,
)
warnings.filterwarnings(
'ignore', "'etree' is deprecated. Use 'xml.etree.ElementTree' instead.",
category=DeprecationWarning, module='wiki'

View File

@@ -10,7 +10,7 @@ from django.contrib.staticfiles.finders import BaseFinder
from django.contrib.staticfiles.storage import FileSystemStorage
from django.core.files.storage import Storage
from django.utils import timezone
from pkg_resources import resource_exists, resource_filename, resource_isdir, resource_listdir
from importlib.resources import files
from xblock.core import XBlock
from openedx.core.lib.xblock_utils import xblock_resource_pkg
@@ -38,7 +38,7 @@ class XBlockPackageStorage(Storage):
"""
Returns a file system filename for the specified file name.
"""
return resource_filename(self.module, os.path.join(self.base_dir, name))
return str(files(self.module).joinpath(self.base_dir, name))
def exists(self, path): # lint-amnesty, pylint: disable=arguments-differ
"""
@@ -47,22 +47,22 @@ class XBlockPackageStorage(Storage):
if self.base_dir is None:
return False
return resource_exists(self.module, os.path.join(self.base_dir, path))
return os.path.exists(os.path.join(self.base_dir, path))
def listdir(self, path):
"""
Lists the directories beneath the specified path.
"""
directories = []
files = []
for item in resource_listdir(self.module, os.path.join(self.base_dir, path)):
files_p = []
for item in files(self.module).joinpath(self.base_dir, path).iterdir():
__, file_extension = os.path.splitext(item)
if file_extension not in [".py", ".pyc", ".scss"]:
if resource_isdir(self.module, os.path.join(self.base_dir, path, item)):
if files(self.module).joinpath(self.base_dir, path, item).is_dir():
directories.append(item)
else:
files.append(item)
return directories, files
files_p.append(item)
return directories, files_p
def open(self, name, mode='rb'):
"""

View File

@@ -9,7 +9,7 @@ That be the dragon here.
"""
import pkg_resources
from importlib.metadata import entry_points
class DuplicateXBlockTest(Exception):
@@ -37,7 +37,7 @@ class InvalidTestName(Exception):
xblock_loaded = False # pylint: disable=invalid-name
for entrypoint in pkg_resources.iter_entry_points(group="xblock.test.v0"):
for entrypoint in entry_points(group="xblock.test.v0"):
plugin = entrypoint.load()
classname = plugin.__name__
if classname in globals():

View File

@@ -1,7 +1,7 @@
"""
Lookup list of installed XBlocks, to aid XBlock developers
"""
import pkg_resources
from importlib.metadata import entry_points
def get_without_builtins():
@@ -12,11 +12,10 @@ def get_without_builtins():
"""
xblocks = [
entry_point.name
for entry_point in pkg_resources.iter_entry_points('xblock.v1')
if not entry_point.module_name.startswith('xmodule')
for entry_point in entry_points(group='xblock.v1')
if not entry_point.module.startswith('xmodule')
]
xblocks = sorted(xblocks)
return xblocks
return sorted(xblocks)
def main():

View File

@@ -17,10 +17,6 @@ filterwarnings =
ignore:Instead access HTTPResponse.headers directly.*:DeprecationWarning:elasticsearch
# ABC deprecation Warning comes from libsass
ignore:Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated.*:DeprecationWarning:sass
# declare_namespace Warning comes from XBlock https://github.com/openedx/XBlock/issues/641
# and also due to dependency: https://github.com/PyFilesystem/pyfilesystem2
ignore:Deprecated call to `pkg_resources.declare_namespace.*:DeprecationWarning
ignore:.*pkg_resources is deprecated as an API.*:DeprecationWarning
ignore:'etree' is deprecated. Use 'xml.etree.ElementTree' instead.:DeprecationWarning:wiki
junit_family = xunit2

View File

@@ -9,7 +9,7 @@ from importlib import import_module
import gettext
import logging
from pkg_resources import resource_filename
from importlib.resources import path as resources_path
import re # lint-amnesty, pylint: disable=wrong-import-order
from django.conf import settings
@@ -422,7 +422,8 @@ class XBlockI18nService:
return 'django', xblock_locale_path
# Pre-OEP-58 translations within the XBlock pip packages are deprecated but supported.
deprecated_xblock_locale_path = resource_filename(xblock_module_name, 'translations')
deprecated_xblock_locale_path = str(resources_path(xblock_module_name, 'translations'))
# The `text` domain was used for XBlocks pre-OEP-58.
return 'text', deprecated_xblock_locale_path

View File

@@ -23,13 +23,13 @@ def test_get_python_locale_with_atlas_oep58_translations(mock_modern_xblock):
assert domain == 'django', 'Uses django domain when atlas locale is found.'
@patch('xmodule.modulestore.django.resource_filename', return_value='/lib/my_legacy_xblock/translations')
@patch('xmodule.modulestore.django.resources_path', return_value='/lib/my_legacy_xblock/translations')
def test_get_python_locale_with_bundled_translations(mock_modern_xblock):
"""
Ensure that get_python_locale() falls back to XBlock internal translations if atlas translations weren't pulled.
Pre-OEP-58 translations were stored in the `translations` directory of the XBlock which is
accessible via the `pkg_resources.resource_filename` function.
accessible via the `importlib.resources.path` function.
"""
i18n_service = XBlockI18nService()
block = mock_modern_xblock['legacy_xblock']

View File

@@ -13,7 +13,8 @@ from django.conf import settings
from lxml import etree
from opaque_keys.edx.asides import AsideDefinitionKeyV2, AsideUsageKeyV2
from opaque_keys.edx.keys import UsageKey
from pkg_resources import resource_isdir, resource_filename
from importlib.resources import files, as_file
from pathlib import Path as P
from web_fragments.fragment import Fragment
from webob import Response
from webob.multidict import MultiDict
@@ -855,32 +856,35 @@ class ResourceTemplates:
@classmethod
def get_template_dir(cls): # lint-amnesty, pylint: disable=missing-function-docstring
if getattr(cls, 'template_dir_name', None):
dirname = os.path.join('templates', cls.template_dir_name) # lint-amnesty, pylint: disable=no-member
if not resource_isdir(__name__, dirname):
dirname = os.path.join('templates', cls.template_dir_name)
if not os.path.isdir(os.path.join(os.path.dirname(__file__), dirname)):
log.warning("No resource directory {dir} found when loading {cls_name} templates".format(
dir=dirname,
cls_name=cls.__name__,
))
return None
else:
return dirname
else:
return None
return dirname
return None
@classmethod
def get_template_dirpaths(cls):
"""
Returns of list of directories containing resource templates.
Returns a list of directories containing resource templates.
"""
template_dirpaths = []
template_dirname = cls.get_template_dir()
if template_dirname and resource_isdir(__name__, template_dirname):
template_dirpaths.append(resource_filename(__name__, template_dirname))
package, module_path = __name__.split('.', 1)
module_dir = str(P(module_path).parent)
module_dir = "" if module_dir == "." else module_dir
file_dirs = files(package).joinpath(module_dir, template_dirname or "")
if template_dirname and file_dirs.is_dir():
with as_file(file_dirs) as path:
template_dirpaths.append(path)
custom_template_dir = cls.get_custom_template_dir()
if custom_template_dir:
template_dirpaths.append(custom_template_dir)
return template_dirpaths
return [str(td) for td in template_dirpaths]
@classmethod
def get_custom_template_dir(cls):