Skip to content

Commit

Permalink
Migrate from pkg_resources to importlib.metadata (#299)
Browse files Browse the repository at this point in the history
  • Loading branch information
mcmtroffaes committed Apr 27, 2022
1 parent 9e9014c commit 051973a
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 22 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
2.4.3 (in development)
2.5.0 (in development)
----------------------

* Add support for the rinohtype builder (reported by brechtm, see issue #275).

* Migrate from ``pkg_resources`` to ``importlib.metadata``. A side effect of
this migration is that
**plugins registered at runtime are longer exposed as entry points**.
This is because ``importlib`` does not allow runtime modification of
entry points.

2.4.2 (10 April 2022)
---------------------

Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ docutils>=0.8
pybtex>=0.24
pybtex-docutils>=1.0.0
dataclasses; python_version < '3.7'
importlib_metadata>=3.6; python_version < '3.10'
49 changes: 33 additions & 16 deletions src/sphinxcontrib/bibtex/plugin.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,47 @@
import pkg_resources
from pybtex.plugin import _FakeEntryPoint
from typing import Type, Any, Dict
import sys
if sys.version_info >= (3, 10):
from importlib.metadata import entry_points, EntryPoint
else:
from importlib_metadata import entry_points, EntryPoint
from typing import Type, Any, Dict, List

_runtime_plugins: Dict[str, Dict[str, Type]] = {
'sphinxcontrib.bibtex.style.referencing': {}}


# wrapper to work around missing type annotations for entry_points function
def _entry_points(group: str, name: str) -> List[EntryPoint]:
return entry_points(group=group, name=name) # type: ignore


def find_plugin(group: str, name: str) -> Type[Any]:
"""Load a sphinxcontrib-bibtex plugin."""
dist = pkg_resources.get_distribution('sphinxcontrib-bibtex')
if group not in dist.get_entry_map():
"""Load a sphinxcontrib-bibtex plugin, either from the runtime store,
or from the entry points.
"""
global _runtime_plugins
if group not in _runtime_plugins:
raise ImportError(f"plugin group {group} not found")
for entry_point in pkg_resources.iter_entry_points(group, name):
return entry_point.load()
try:
return _runtime_plugins[group][name]
except KeyError:
for entry_point in _entry_points(group=group, name=name):
return entry_point.load()
raise ImportError(f"plugin {group}.{name} not found")


def register_plugin(group: str, name: str, klass: Type[Any],
force: bool = False) -> bool:
"""Register a sphinxcontrib-bibtex plugin at runtime."""
dist = pkg_resources.get_distribution('sphinxcontrib-bibtex')
entry_map: Dict[str, Dict[str, pkg_resources.EntryPoint]] \
= dist.get_entry_map()
"""Register a sphinxcontrib-bibtex plugin into the runtime store."""
global _runtime_plugins
if group not in _runtime_plugins:
raise ImportError(f"plugin group {group} not found")
eps: List[Any]
try:
entry_points = entry_map[group]
eps = [_runtime_plugins[group][name]]
except KeyError:
raise ImportError(f"plugin group {group} not found")
if name not in entry_points or force:
entry_points[name] = _FakeEntryPoint(name, klass)
eps = _entry_points(group=group, name=name)
if not eps or force:
_runtime_plugins[group][name] = klass
return True
else:
return False
10 changes: 5 additions & 5 deletions src/sphinxcontrib/bibtex/style/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
from sphinxcontrib.bibtex.nodes import raw_latex
from sphinxcontrib.bibtex.richtext import BaseReferenceText

from typing import TYPE_CHECKING, Dict, Any, cast, NamedTuple
from typing import TYPE_CHECKING, Dict, Any, cast, NamedTuple, List

if TYPE_CHECKING:
from pybtex.backends import BaseBackend
Expand Down Expand Up @@ -123,7 +123,7 @@ class SphinxReferenceText(BaseReferenceText[SphinxReferenceInfo]):
for use with :class:`SphinxReferenceInfo`.
"""

def render(self, backend: "BaseBackend"):
def render(self, backend: "BaseBackend") -> List[docutils.nodes.Element]:
assert isinstance(backend, pybtex_docutils.Backend), \
"SphinxReferenceText only supports the docutils backend"
info = self.info[0]
Expand All @@ -144,16 +144,16 @@ def render(self, backend: "BaseBackend"):
else:
children = super().render(backend)
# make_refnode only takes a single child
refnode = make_refnode(
refnode2 = make_refnode(
builder=info.builder,
fromdocname=info.fromdocname,
todocname=info.todocname,
targetid=info.citation_id,
child=children[0],
title=info.title,
)
refnode.extend(children[1:]) # type: ignore
return [refnode]
refnode2.extend(children[1:]) # type: ignore
return [refnode2]


@node
Expand Down

0 comments on commit 051973a

Please sign in to comment.