Skip to content

types

Simple types and utilities for plugins.

SemVerTuple module-attribute

SemVerTuple: TypeAlias = Tuple[
    NonNegativeInt, NonNegativeInt, NonNegativeInt
]

Type to be used for SemVer triples.

NAME module-attribute

NAME: Final[str] = f'{LETTER}{ALNUM}({LETSEP}?{ALNUM})*'

An unqualified name begins with a letter and ends with a letter or number.

It consists of: lowercase letters, digits, _ and -

QUAL_NAME module-attribute

QUAL_NAME: Final[str] = f'{NAME}({NSSEP}{NAME})*'

A qualified name is a sequence of unqualified names separated with .

EP_NAME_VER_SEP module-attribute

EP_NAME_VER_SEP: str = '__'

Separator between plugin name and semantic version in entry point name.

EP_NAME_REGEX module-attribute

EP_NAME_REGEX: Final[
    str
] = f"{QUAL_NAME}{EP_NAME_VER_SEP}{SEMVER_STR_REGEX}"

Regular expression that all metador plugin entry points must match.

PG_PREFIX module-attribute

PG_PREFIX: str = 'metador_'

Group prefix for metador plugin entry point groups.

SemVerStr

Bases: FullMatch

Semantic version string (x.y.z).

Source code in src/metador_core/plugin/types.py
17
18
class SemVerStr(FullMatch, pattern=SEMVER_STR_REGEX):
    """Semantic version string (x.y.z)."""

EPName

Bases: FullMatch

Valid entry point for a metador plugin.

Source code in src/metador_core/plugin/types.py
51
52
class EPName(FullMatch, pattern=EP_NAME_REGEX):
    """Valid entry point for a metador plugin."""

EPGroupName

Bases: FullMatch

Valid internal group name for a metador plugin group.

Source code in src/metador_core/plugin/types.py
76
77
class EPGroupName(FullMatch, pattern=rf"{PG_PREFIX}.*"):
    """Valid internal group name for a metador plugin group."""

PluginLike

Bases: Protocol

A Plugin has a Plugin inner class with plugin infos.

Source code in src/metador_core/plugin/types.py
96
97
98
99
class PluginLike(Protocol):
    """A Plugin has a Plugin inner class with plugin infos."""

    Plugin: ClassVar[Any]  # actually its PluginBase, but this happens at runtime

to_ep_name

to_ep_name(p_name: str, p_version: SemVerTuple) -> EPName

Return canonical entrypoint name PLUGIN_NAME__MAJ.MIN.FIX.

Source code in src/metador_core/plugin/types.py
55
56
57
def to_ep_name(p_name: str, p_version: SemVerTuple) -> EPName:
    """Return canonical entrypoint name `PLUGIN_NAME__MAJ.MIN.FIX`."""
    return EPName(f"{p_name}{EP_NAME_VER_SEP}{to_semver_str(p_version)}")

from_ep_name

from_ep_name(ep_name: EPName) -> Tuple[str, SemVerTuple]

Split entrypoint name into (PLUGIN_NAME, (MAJ,MIN,FIX)).

Source code in src/metador_core/plugin/types.py
60
61
62
63
def from_ep_name(ep_name: EPName) -> Tuple[str, SemVerTuple]:
    """Split entrypoint name into `(PLUGIN_NAME, (MAJ,MIN,FIX))`."""
    pname, pverstr = ep_name.split(EP_NAME_VER_SEP)
    return (pname, from_semver_str(SemVerStr(pverstr)))

ep_name_has_namespace

ep_name_has_namespace(ep_name: EPName)

Check whether the passed name has a namespace prefix.

Source code in src/metador_core/plugin/types.py
66
67
68
69
def ep_name_has_namespace(ep_name: EPName):
    """Check whether the passed name has a namespace prefix."""
    name, ver = from_ep_name(ep_name)
    return len(name.split(".", 1)) > 1

plugin_args

plugin_args(
    plugin="",
    version: Optional[SemVerTuple] = None,
    *,
    require_version: bool = False
) -> Tuple[str, Optional[SemVerTuple]]

Return requested plugin name and version based on passed arguments.

Helper for function argument parsing.

Source code in src/metador_core/plugin/types.py
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
def plugin_args(
    plugin="",  # actually takes: Union[str, PluginRef, PluginLike]
    version: Optional[SemVerTuple] = None,
    *,
    require_version: bool = False,
    # group: Optional[str]
) -> Tuple[str, Optional[SemVerTuple]]:
    """Return requested plugin name and version based on passed arguments.

    Helper for function argument parsing.
    """
    name: str = ""
    vers: Optional[SemVerTuple] = version

    if isinstance(plugin, str):
        name = plugin
    if isinstance(plugin, tuple) and len(plugin) == 2:
        name = plugin[0]
        if not vers:
            vers = plugin[1]
    elif isinstance(plugin, HasNameVersion):
        name = plugin.name
        if not vers:
            vers = plugin.version
    elif pgi := getattr(plugin, "Plugin", None):
        if isinstance(pgi, HasNameVersion):
            return plugin_args(pgi, version, require_version=require_version)

    if require_version and vers is None:
        raise ValueError(f"No version of {name} specified, but is required!")
    return (name, vers)