Source code for zensols.util.pkgres
"""A convenience class around the :mod:`pkg_resources` module.
"""
__author__ = 'Paul Landes'
from typing import Optional
from dataclasses import dataclass, field
import logging
from pathlib import Path
import pkg_resources as pkg
logger = logging.getLogger(__name__)
[docs]
@dataclass
class PackageResource(object):
"""Contains resources of installed Python packages. It makes the
:obj:`distribution` available and provides access to to resource files with
:meth:`get_path` and as an index.
"""
name: str = field()
"""The name of the module (i.e. zensols.someappname)."""
file_system_defer: bool = field(default=True)
"""Whether or not to return resource paths that point to the file system when
this package distribution does not exist.
:see: :meth:`get_path`
"""
@property
def distribution(self) -> Optional[pkg.DistInfoDistribution]:
"""The package distribution.
:return: the distribution or ``None`` if it is not installed
"""
if not hasattr(self, '_dist'):
try:
self._dist = pkg.get_distribution(self.name)
except pkg.DistributionNotFound:
logger.info(f'no distribution found: {self.name}')
self._dist = None
return self._dist
@property
def exists(self) -> bool:
"""Return if the package exists and installed.
"""
return self.distribution is not None
@property
def version(self) -> Optional[str]:
"""Return the version if the package exists.
"""
if self.exists:
return self.distribution.version
[docs]
def get_path(self, resource: str) -> Optional[Path]:
"""Return a resource file name by name. Optionally return resource as a
relative path if the package does not exist.
:param resource: a forward slash (``/``) delimited path
(i.e. ``resources/app.conf``) of the resource name
:return: a path to that resource on the file system or ``None`` if the
package doesn't exist, the resource doesn't exist and
:obj:`file_system_defer` is ``False``
"""
res_name = str(Path(*resource.split('/')))
path = None
if self.exists and pkg.resource_exists(self.name, res_name):
path = pkg.resource_filename(self.name, res_name)
path = Path(path)
else:
path = Path(res_name)
return path
def __getitem__(self, resource: str) -> Path:
if not self.exists:
raise KeyError(f'package does not exist: {self.name}')
res = self.get_path(resource)
if res is None:
raise KeyError(f'no such resource file: {resource}')
return res
def __str__(self) -> str:
if self.exists:
return str(self.distribution)
else:
return self.name