fix: migrate pkg_resources lib to importlib

This commit is contained in:
ievgenii vdovenko 2025-10-03 14:49:50 +02:00
parent ed5efcccfe
commit 695b0db001
7 changed files with 56 additions and 25 deletions

View file

@ -7,7 +7,6 @@ import shutil
import string
import logging
from pkg_resources import resource_filename
from tempita import Template as TempitaTemplate
from rhodecode.lib.dbmigrate.migrate import exceptions
@ -64,7 +63,7 @@ class Changeset(dict):
def run(self, *p, **k):
"""Run the changeset scripts"""
for version, script in self:
for _, script in self:
script.run(*p, **k)

View file

@ -1,12 +1,9 @@
#!/usr/bin/env python
import importlib
import os
import shutil
import sys
from pkg_resources import resource_filename
from rhodecode.lib.dbmigrate.migrate.versioning.config import *
from rhodecode.lib.dbmigrate.migrate.versioning import pathed
@ -65,9 +62,14 @@ class Template(pathed.Pathed):
tmp_pkg = pkg.rsplit(".", 1)
if len(tmp_pkg) != 1:
return resource_filename(tmp_pkg[0], tmp_pkg[1])
module = tmp_pkg[0]
resource = tmp_pkg[1]
else:
return resource_filename(tmp_pkg[0], "")
module = tmp_pkg[0]
resource = ""
with importlib.resources.as_file(importlib.resources.files(module).joinpath(resource)) as static_path:
return str(static_path)
def _get_item(self, collection, theme=None):
"""Locates and returns collection.

View file

@ -2,10 +2,10 @@
""".. currentmodule:: migrate.versioning.util"""
import importlib
import warnings
import logging
from decorator import decorator
from pkg_resources import EntryPoint
from sqlalchemy import create_engine
from sqlalchemy.engine import Engine
@ -19,6 +19,19 @@ from rhodecode.lib.dbmigrate.migrate.versioning.util.importpath import import_pa
log = logging.getLogger(__name__)
def load_dotted(dotted: str):
"""
Load an object from 'package.module:qual.name' or just 'package.module'.
Mirrors pkg_resources.EntryPoint(...).load(require=False).
"""
module_name, sep, qual = dotted.partition(":")
obj = importlib.import_module(module_name)
if sep: # ':...' present -> walk attributes
for attr in qual.split("."):
obj = getattr(obj, attr)
return obj
def load_model(dotted_name):
"""Import module and use module-level variable".
@ -35,7 +48,7 @@ def load_model(dotted_name):
exceptions.MigrateDeprecationWarning,
)
dotted_name = ":".join(dotted_name.rsplit(".", 1))
return EntryPoint.parse("x=%s" % dotted_name).load(False)
return load_dotted(dotted_name)
else:
# Assume it's already loaded.
return dotted_name
@ -69,13 +82,13 @@ def guess_obj_type(obj):
try:
result = int(obj)
except:
except Exception as e:
pass
if result is None:
try:
result = asbool(obj)
except:
except Exception as e:
pass
if result is not None:

View file

@ -15,12 +15,10 @@
# This program is dual-licensed. If you wish to learn more about the
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
import importlib
import os
import logging
from pathlib import Path
from pkg_resources import resource_filename
from mako import exceptions
from pyramid.asset import resolve_asset_spec
@ -59,7 +57,10 @@ class PyramidPartialRenderer(object):
if not self.tmpl_path:
package, filename = resolve_asset_spec(self.tmpl_name)
template_path = os.path.dirname(resource_filename(package, filename))
with importlib.resources.as_file(importlib.resources.files(package).joinpath(filename)) as static_path:
template_path = os.path.dirname(str(static_path))
self.tmpl_path = Path(template_path).as_posix()
log.debug(f"Using {self.tmpl_path} path")
_tmpl_lookup = TemplateLookup([self.tmpl_path])

View file

@ -38,7 +38,6 @@ from functools import wraps
from os.path import join as jn
import paste
import pkg_resources
from webhelpers2.text import collapse, strip_tags, convert_accented_entities, convert_misc_entities
from mako import exceptions
@ -890,7 +889,7 @@ def read_opensource_licenses():
global _license_cache
if not _license_cache:
licenses = pkg_resources.resource_string("rhodecode", "config/licenses.json")
licenses = importlib.resources.files("rhodecode").joinpath("config/licenses.json").read_bytes()
_license_cache = json.loads(licenses)
return _license_cache

View file

@ -39,11 +39,12 @@ for SELECT use formencode.All(OneOf(list), Int())
"""
import importlib
import deform
import logging
import formencode
from pkg_resources import resource_filename
from formencode import All, Pipe
from rhodecode.lib.pyramid_utils import get_current_request
@ -54,9 +55,14 @@ from rhodecode.model import validators as v
log = logging.getLogger(__name__)
with importlib.resources.as_file(importlib.resources.files("deform").joinpath("templates")) as templates_path:
deform_templates = str(templates_path)
with importlib.resources.as_file(
importlib.resources.files("rhodecode").joinpath("templates/forms")
) as templates_forms_path:
rhodecode_templates = str(templates_forms_path)
deform_templates = resource_filename("deform", "templates")
rhodecode_templates = resource_filename("rhodecode", "templates/forms")
search_path = (rhodecode_templates, deform_templates)

View file

@ -357,6 +357,16 @@ class TestPasswordChanged(object):
class TestReadOpenSourceLicenses(object):
def test_success(self):
class _FakeFile:
def __init__(self, data: bytes):
self._data = data
def joinpath(self, *parts): # keep chaining compatible
return self
def read_bytes(self):
return self._data
utils._license_cache = None
json_data = """
{
@ -366,8 +376,7 @@ class TestReadOpenSourceLicenses(object):
}
}
"""
resource_string_patch = mock.patch.object(utils.pkg_resources, "resource_string", return_value=json_data)
with resource_string_patch:
with mock.patch.object(utils.importlib.resources, "files", return_value=_FakeFile(json_data)):
result = utils.read_opensource_licenses()
assert result == json.loads(json_data)
@ -376,10 +385,12 @@ class TestReadOpenSourceLicenses(object):
"python2.7-pytest-2.7.1": {"UNKNOWN": None},
"python2.7-Markdown-2.6.2": {"BSD-3-Clause": "http://spdx.org/licenses/BSD-3-Clause"},
}
resource_patch = mock.patch.object(utils.pkg_resources, "resource_string", side_effect=Exception)
json_patch = mock.patch.object(utils.json, "loads", side_effect=Exception)
with resource_patch as resource_mock, json_patch as json_mock:
with (
mock.patch.object(utils.importlib.resources, "files", side_effect=Exception) as resource_mock,
json_patch as json_mock,
):
result = utils.read_opensource_licenses()
assert resource_mock.call_count == 0