diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/repository.py b/rhodecode/lib/dbmigrate/migrate/versioning/repository.py index d4223f8d..23335178 100644 --- a/rhodecode/lib/dbmigrate/migrate/versioning/repository.py +++ b/rhodecode/lib/dbmigrate/migrate/versioning/repository.py @@ -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) diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/template.py b/rhodecode/lib/dbmigrate/migrate/versioning/template.py index 24b3000e..26874776 100644 --- a/rhodecode/lib/dbmigrate/migrate/versioning/template.py +++ b/rhodecode/lib/dbmigrate/migrate/versioning/template.py @@ -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. diff --git a/rhodecode/lib/dbmigrate/migrate/versioning/util/__init__.py b/rhodecode/lib/dbmigrate/migrate/versioning/util/__init__.py index 61ebc925..9a086c0f 100644 --- a/rhodecode/lib/dbmigrate/migrate/versioning/util/__init__.py +++ b/rhodecode/lib/dbmigrate/migrate/versioning/util/__init__.py @@ -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: diff --git a/rhodecode/lib/partial_renderer.py b/rhodecode/lib/partial_renderer.py index 253726c1..bce0326c 100644 --- a/rhodecode/lib/partial_renderer.py +++ b/rhodecode/lib/partial_renderer.py @@ -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]) diff --git a/rhodecode/lib/utils.py b/rhodecode/lib/utils.py index f58e76e9..998352a7 100644 --- a/rhodecode/lib/utils.py +++ b/rhodecode/lib/utils.py @@ -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 diff --git a/rhodecode/model/forms.py b/rhodecode/model/forms.py index 8e1afc95..31ae0c79 100644 --- a/rhodecode/model/forms.py +++ b/rhodecode/model/forms.py @@ -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) diff --git a/rhodecode/tests/lib/test_utils.py b/rhodecode/tests/lib/test_utils.py index 775bdb7b..f3505ab2 100644 --- a/rhodecode/tests/lib/test_utils.py +++ b/rhodecode/tests/lib/test_utils.py @@ -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