Skip to content

Commit

Permalink
importlib_resources is only needed in Python 3.8
Browse files Browse the repository at this point in the history
Add type hints + fixes
  • Loading branch information
mr-c committed Nov 24, 2023
1 parent 97575b4 commit ffc963b
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 35 deletions.
9 changes: 4 additions & 5 deletions lib/galaxy/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,10 @@
if TYPE_CHECKING:
from galaxy.model import User

try:
from importlib.resources import files # type: ignore[attr-defined]
except ImportError:
# Python < 3.9
from importlib_resources import files # type: ignore[no-redef]
if sys.version_info >= (3, 9):
from importlib.resources import files
else:
from importlib_resources import files

log = logging.getLogger(__name__)

Expand Down
9 changes: 6 additions & 3 deletions lib/galaxy/config/templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,17 @@

from jinja2 import Environment

from galaxy.util.resources import resource_path
from galaxy.util.resources import (
resource_path,
Traversable,
)

TEMPLATE_SEP = ">>>>>>" # Used to split templates into doc/body sections


def render(template_path: str, context: dict, custom_templates_dir: str) -> str:
"""Read and return templated content as string."""
with open(_get_template_path(template_path, custom_templates_dir)) as f:
with _get_template_path(template_path, custom_templates_dir).open() as f:
template_str = _get_template_body(f.read())
tmpl = Environment().from_string(template_str)
return tmpl.render(**context)
Expand All @@ -28,7 +31,7 @@ def _get_template_body(template: str) -> str:
return template.split(TEMPLATE_SEP, 1)[-1].split("\n", 1)[1]


def _get_template_path(relpath: str, custom_templates_dir: str) -> Path:
def _get_template_path(relpath: str, custom_templates_dir: str) -> Traversable:
"""Return template file path."""
default_path = resource_path("galaxy.config", "templates") / relpath
custom_path = Path(custom_templates_dir) / relpath
Expand Down
43 changes: 29 additions & 14 deletions lib/galaxy/util/resources.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,38 @@
"""Provide a consistent interface into and utilities for importlib file resources.
"""
try:
from importlib.abc import Traversable # type: ignore[attr-defined]
from importlib.resources import files # type: ignore[attr-defined]
except ImportError:
# Python < 3.9
from importlib_resources import files # type: ignore[no-redef]
from importlib_resources.abc import Traversable # type: ignore[no-redef]


def resource_path(package_or_requirement, resource_name):
import sys

if sys.version_info >= (3, 12):
from importlib.resources import (
Anchor,
as_file,
files,
)
from importlib.resources.abc import Traversable
elif sys.version_info >= (3, 9):
from importlib.abc import Traversable
from importlib.resources import (
as_file,
files,
Package as Anchor,
)
else:
from importlib_resources import (
as_file,
files,
Package as Anchor,
)
from importlib_resources.abc import Traversable


def resource_path(package_or_requirement: Anchor, resource_name: str) -> Traversable:
"""
Return specified resource as a string.
Replacement function for pkg_resources.resource_string, but returns unicode string instead of bytestring.
Return specified resource as a Traversable.
"""
return files(package_or_requirement).joinpath(resource_name)


def resource_string(package_or_requirement, resource_name) -> str:
def resource_string(package_or_requirement: Anchor, resource_name: str) -> str:
"""
Return specified resource as a string.
Expand All @@ -28,6 +42,7 @@ def resource_string(package_or_requirement, resource_name) -> str:


__all__ = (
"as_file",
"files",
"resource_string",
"resource_path",
Expand Down
2 changes: 1 addition & 1 deletion packages/util/setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ install_requires =
bleach
boltons
docutils!=0.17,!=0.17.1
importlib_resources
importlib-resources;python_version<'3.9'
packaging
pyparsing
PyYAML
Expand Down
2 changes: 1 addition & 1 deletion packages/web_apps/setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ install_requires =
fastapi-utils
gunicorn
gxformat2
importlib_resources
importlib-resources;python_version<'3.9'
Mako
MarkupSafe
mercurial
Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ gxformat2 = "*"
h5grove = ">=1.2.1"
h5py = "*"
importlib-metadata = "<5" # Work around https://github.com/celery/kombu/issues/1600
importlib-resources = "*"
importlib-resources = { version = "*", python = "<3.9" } # for importlib.{abc.Traversable,resources.{files, Package}}
isa-rwval = ">=0.10.10"
kombu = "*"
lagom = "*"
Expand Down Expand Up @@ -167,6 +167,7 @@ watchdog = "*"

[tool.poetry.group.typecheck.dependencies]
mypy = "*"
lxml-stubs = "*"
pydantic = "<2" # for pydantic.mypy plugin
types-bleach = "*"
types-boto = "*"
Expand Down
16 changes: 11 additions & 5 deletions test/unit/data/model/migrations/test_migrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@
drop_existing_database,
url_factory,
)
from galaxy.util.resources import resource_path
from galaxy.util.resources import (
as_file,
resource_path,
)

# Revision numbers from test versions directories
GXY_REVISION_0 = "62695fac6cc0" # oldest/base
Expand Down Expand Up @@ -1128,10 +1131,13 @@ def db_state6_gxy_state3_tsi_no_sam(url_factory, metadata_state6_gxy_state3_tsi_
@pytest.fixture(autouse=True)
def legacy_manage_db(monkeypatch):
def get_alembic_cfg():
path = resource_path("galaxy.model.migrations", "alembic.ini")
config = Config(path)
path1, path2 = _get_paths_to_version_locations()
config.set_main_option("version_locations", f"{path1};{path2}")
traversable = resource_path("galaxy.model.migrations", "alembic.ini")
with as_file(traversable) as path:
config = Config(path)
path1, path2 = _get_paths_to_version_locations()
config.set_main_option("version_locations", f"{path1};{path2}")
# config.set_main_option() calls config.file_config() which memoizes
# the temporary file path from the as_file() contextmanager
return config

monkeypatch.setattr(galaxy.model.migrations.scripts, "get_alembic_cfg", get_alembic_cfg)
Expand Down
13 changes: 8 additions & 5 deletions test/unit/tool_util/data/test_tool_data_bundles.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@
galaxy_directory,
parse_xml,
)
from galaxy.util.resources import resource_path
from galaxy.util.resources import (
as_file,
resource_path,
)

TOOLS_DIRECTORY = os.path.abspath(os.path.join(galaxy_directory(), "test/functional/tools/"))

Expand Down Expand Up @@ -51,8 +54,8 @@ def test_xml_parsing() -> None:


def test_parsing_manual() -> None:
path = resource_path(__package__, "example_data_managers/manual.xml")
tree = parse_xml(path)
with as_file(resource_path(__package__, "example_data_managers/manual.xml")) as path:
tree = parse_xml(path)
data_managers_el = tree.getroot()
data_manager_el = data_managers_el.find("data_manager")
description = convert_data_tables_xml(data_manager_el)
Expand All @@ -61,8 +64,8 @@ def test_parsing_manual() -> None:


def test_parsing_mothur() -> None:
path = resource_path(__package__, "example_data_managers/mothur.xml")
tree = parse_xml(path)
with as_file(resource_path(__package__, "example_data_managers/mothur.xml")) as path:
tree = parse_xml(path)
data_managers_el = tree.getroot()
data_manager_el = data_managers_el.find("data_manager")
description = convert_data_tables_xml(data_manager_el)
Expand Down

0 comments on commit ffc963b

Please sign in to comment.