"""
Base classes, commong types and functions for the `core` module.
"""
from __future__ import annotations
import typing as t
from abc import ABCMeta, abstractmethod
from collections import abc, UserDict
from io import TextIOBase
from pathlib import Path
from typing import runtime_checkable
import msgpack
T = t.TypeVar("T")
_T = t.TypeVar("_T", contravariant=True)
_Fetcher = abc.Callable[[abc.Iterable[str]], T]
_Getter = abc.Callable[[T, abc.Sequence[str]], abc.Sequence[str]]
_MapT = dict[int, int | None]
ALL21 = Path(__file__).parent.parent / "resources" / "all21.msgpack"
[docs]
class ResNameDict(UserDict):
"""
A dictionary providing mapping between PDB residue names and their
one-letter codes. The mapping was parsed from the CCD and can be obtained
by calling :meth:`lXtractor.ext.ccd.CCD.make_res_name_map`.
>>> d = ResNameDict()
>>> assert d['ALA'] == 'A'
"""
[docs]
def __init__(self):
from lXtractor.core.exceptions import MissingData
if not ALL21.exists():
raise MissingData(f"Missing parsed all-to-one mapping in {ALL21}")
with ALL21.open("rb") as f:
unpacker = msgpack.Unpacker(f)
all21 = unpacker.unpack()
super().__init__(all21)
[docs]
class AbstractResource(metaclass=ABCMeta):
"""
Abstract base class defining basic interface any resource must provide.
"""
[docs]
def __init__(self, resource_path: str | Path, resource_name: str | None):
"""
:param resource_path: Path to parsed resource data.
:param resource_name: Resource's name.
"""
self.name = resource_name
self.path = resource_path
[docs]
@abstractmethod
def read(self):
"""
Read the resource using the :attr:`resource_path`
"""
raise NotImplementedError
[docs]
@abstractmethod
def parse(self):
"""
Parse the read resource, so it's ready for usage.
"""
raise NotImplementedError
[docs]
@abstractmethod
def dump(self, path: Path):
"""
Save the resource under the given `path`.
"""
raise NotImplementedError
[docs]
@abstractmethod
def fetch(self, url: str):
"""
Download the resource.
"""
raise NotImplementedError
[docs]
@t.runtime_checkable
class Ord(t.Protocol[_T]):
"""
Any objects defining comparison operators.
"""
def __le__(self, other: _T) -> bool:
...
def __ge__(self, other: _T) -> bool:
...
def __eq__(self, other: object) -> bool:
...
[docs]
@runtime_checkable
class SupportsWrite(t.Protocol):
"""
Any object with the `write` method.
"""
[docs]
def write(self, data):
"""
Write the supplied data.
"""
[docs]
@runtime_checkable
class AddMethod(t.Protocol):
"""
A callable to add sequences to the aligned ones,
preserving the alignment length.
"""
[docs]
def __call__(
self,
msa: abc.Iterable[tuple[str, str]] | Path,
seqs: abc.Iterable[tuple[str, str]],
# **kwargs,
) -> abc.Iterable[tuple[str, str]]:
...
[docs]
@runtime_checkable
class AlignMethod(t.Protocol):
"""
A callable to align arbitrary sequences.
"""
[docs]
def __call__(
self, seqs: abc.Iterable[tuple[str, str]] | Path
) -> abc.Iterable[tuple[str, str]]:
...
[docs]
class SeqReader(t.Protocol):
"""
A callable reading sequences into tuples of (header, _seq) pairs.
"""
[docs]
def __call__(
self, inp: Path | TextIOBase | abc.Iterable[str]
) -> abc.Iterable[tuple[str, str]]:
...
[docs]
class SeqWriter(t.Protocol):
"""
A callable writing (header, _seq) pairs to disk.
"""
[docs]
def __call__(
self,
inp: abc.Iterable[tuple[str, str]],
out: Path | SupportsWrite,
# **kwargs
) -> None:
...
[docs]
class SeqMapper(t.Protocol):
"""
A callable accepting and returning a pair (header, _seq).
"""
[docs]
def __call__(self, seq: tuple[str, str], **kwargs) -> tuple[str, str]:
...
[docs]
class SeqFilter(t.Protocol):
"""
A callable accepting a pair (header, _seq) and returning a boolean.
"""
[docs]
def __call__(self, seq: tuple[str, str], **kwargs) -> bool:
...
[docs]
class UrlGetter(t.Protocol):
"""
A callable accepting some string arguments and turning them into a
valid url.
"""
[docs]
def __call__(self, *args) -> str:
...
[docs]
@t.runtime_checkable
class ApplyTWithArgs(t.Protocol[T]):
[docs]
def __call__(self, x: T, *args, **kwargs) -> T:
...
# ApplyT = abc.Callable[[T], T]
[docs]
@t.runtime_checkable
class ApplyT(t.Protocol[T]):
[docs]
def __call__(self, x: T) -> T:
...
[docs]
@t.runtime_checkable
class FilterT(t.Protocol[T]):
[docs]
def __call__(self, x: T) -> bool:
...
[docs]
@t.runtime_checkable
class NamedTupleT(t.Protocol, abc.Iterable):
def __getattr__(self, item):
...
def _asdict(self) -> dict[str, t.Any]:
...
if __name__ == "__main__":
raise RuntimeError