Skip to content

lib

Main Cridlib library.

CRID

Represent CRIDs and can parse, validate and render them.

Examples

Generate a CRID from an URL and render it's repr:
```python
>>> CRID("crid://rabe.ch/v1/test#t=clock=19930301T131200.00Z")
<class 'cridlib.lib.CRID' for 'crid://rabe.ch/v1/test#t=clock=19930301T131200.00Z'>

```

Generate a CRID and render it as str:
```python
>>> str(CRID("crid://rabe.ch/v1/test#t=clock=19930301T131200.00Z"))
'crid://rabe.ch/v1/test#t=clock=19930301T131200.00Z'

```
Source code in cridlib/lib.py
class CRID:
    """Represent CRIDs and can parse, validate and render them.

    Examples
    --------
        Generate a CRID from an URL and render it's repr:
        ```python
        >>> CRID("crid://rabe.ch/v1/test#t=clock=19930301T131200.00Z")
        <class 'cridlib.lib.CRID' for 'crid://rabe.ch/v1/test#t=clock=19930301T131200.00Z'>

        ```

        Generate a CRID and render it as str:
        ```python
        >>> str(CRID("crid://rabe.ch/v1/test#t=clock=19930301T131200.00Z"))
        'crid://rabe.ch/v1/test#t=clock=19930301T131200.00Z'

        ```

    """

    def __init__(self: Self, uri: str | None = None) -> None:
        """Create new CRID.

        Args:
        ----
            uri: CRID URL to base the new CRID off of.

        """
        self._show: str | None = None
        self._start: datetime | None = None

        self._uri = urisplit(uri)
        if self.scheme != "crid":
            raise CRIDSchemeMismatchError(self.scheme, uri)
        if self.authority != "rabe.ch":
            raise CRIDSchemeAuthorityMismatchError(self.authority, uri)
        # parent.stem contains version in /v1/foo paths, stem in generic root /v1 path
        if self.path.parent.stem != "v1" and self.path.stem != "v1":
            raise CRIDUnsupportedVersionError(self.path, uri)
        self._version = self.path.parent.stem or self.path.stem
        # only store show if we have one
        if self.path.stem != "v1":
            self._show = self.path.relative_to(self.path.parent).stem
        # fragments are optional, but if provided we want them to contain t=code
        if self.fragment:
            try:
                # TODO(hairmare): investigate noqa for bug
                # https://github.com/radiorabe/python-rabe-cridlib/issues/244
                self._start = datetime.strptime(  # noqa: DTZ007
                    parse_qs(parse_qs(self.fragment)["t"][0])["clock"][0],
                    "%Y%m%dT%H%M%S.%fZ",
                )
            except KeyError as ex:
                raise CRIDMissingMediaFragmentError(self.fragment, uri) from ex
            except ValueError as ex:  # pragma: no cover
                raise CRIDMalformedMediaFragmentError(self.fragment, uri) from ex

    def __str__(self: Self) -> str:
        """Stringfy.

        Returns
        -------
            CRID URL rendered as string.

        """
        return uricompose(*self._uri)

    def __repr__(self: Self) -> str:
        """Repr."""
        _fqcn = f"{self.__class__.__module__}.{self.__class__.__qualname__}"
        return f"<class '{_fqcn}' for '{self!s}'>"

    @property
    def scheme(self: Self) -> str:
        """Scheme.

        Returns
        -------
            Scheme part of the CRID.

        """
        return self._uri.scheme

    @property
    def authority(self: Self) -> str:
        """Authority.

        Returns
        -------
            Authority part (aka hostname) of CRID.

        """
        return self._uri.authority

    @property
    def path(self: Self) -> CRIDPath:
        """Path.

        Returns
        -------
            Path part of CRID.

        """
        return CRIDPath(self._uri.path)

    @property
    def fragment(self: Self) -> str:
        """Fragment.

        Returns
        -------
            Fragment part of CRID.

        """
        return self._uri.fragment

    @property
    def version(self: Self) -> str:
        """Version.

        Returns
        -------
            Version from CRIDs path.

        """
        return self._version

    @property
    def show(self: Self) -> str | None:
        """Slug.

        Returns
        -------
            Show slug from CRIDs path.

        """
        return self._show

    @property
    def start(self: Self) -> datetime | None:
        """Start time.

        Returns
        -------
            Start time form CRIDs media fragment.

        """
        return self._start

authority: str property

Authority.

Returns
Authority part (aka hostname) of CRID.

fragment: str property

Fragment.

Returns
Fragment part of CRID.

path: CRIDPath property

Path.

Returns
Path part of CRID.

scheme: str property

Scheme.

Returns
Scheme part of the CRID.

show: str | None property

Slug.

Returns
Show slug from CRIDs path.

start: datetime | None property

Start time.

Returns
Start time form CRIDs media fragment.

version: str property

Version.

Returns
Version from CRIDs path.

__init__(uri=None)

Create new CRID.


uri: CRID URL to base the new CRID off of.
Source code in cridlib/lib.py
def __init__(self: Self, uri: str | None = None) -> None:
    """Create new CRID.

    Args:
    ----
        uri: CRID URL to base the new CRID off of.

    """
    self._show: str | None = None
    self._start: datetime | None = None

    self._uri = urisplit(uri)
    if self.scheme != "crid":
        raise CRIDSchemeMismatchError(self.scheme, uri)
    if self.authority != "rabe.ch":
        raise CRIDSchemeAuthorityMismatchError(self.authority, uri)
    # parent.stem contains version in /v1/foo paths, stem in generic root /v1 path
    if self.path.parent.stem != "v1" and self.path.stem != "v1":
        raise CRIDUnsupportedVersionError(self.path, uri)
    self._version = self.path.parent.stem or self.path.stem
    # only store show if we have one
    if self.path.stem != "v1":
        self._show = self.path.relative_to(self.path.parent).stem
    # fragments are optional, but if provided we want them to contain t=code
    if self.fragment:
        try:
            # TODO(hairmare): investigate noqa for bug
            # https://github.com/radiorabe/python-rabe-cridlib/issues/244
            self._start = datetime.strptime(  # noqa: DTZ007
                parse_qs(parse_qs(self.fragment)["t"][0])["clock"][0],
                "%Y%m%dT%H%M%S.%fZ",
            )
        except KeyError as ex:
            raise CRIDMissingMediaFragmentError(self.fragment, uri) from ex
        except ValueError as ex:  # pragma: no cover
            raise CRIDMalformedMediaFragmentError(self.fragment, uri) from ex

__repr__()

Repr.

Source code in cridlib/lib.py
def __repr__(self: Self) -> str:
    """Repr."""
    _fqcn = f"{self.__class__.__module__}.{self.__class__.__qualname__}"
    return f"<class '{_fqcn}' for '{self!s}'>"

__str__()

Stringfy.

Returns
CRID URL rendered as string.
Source code in cridlib/lib.py
def __str__(self: Self) -> str:
    """Stringfy.

    Returns
    -------
        CRID URL rendered as string.

    """
    return uricompose(*self._uri)

CRIDError

Bases: Exception

Represent all cridlib errors.

Source code in cridlib/lib.py
class CRIDError(Exception):
    """Represent all cridlib errors."""

CRIDMalformedMediaFragmentError

Bases: CRIDError

Missing media-fragment with clock code.

Source code in cridlib/lib.py
class CRIDMalformedMediaFragmentError(CRIDError):
    """Missing media-fragment with clock code."""

CRIDMissingMediaFragmentError

Bases: CRIDError

Missing media-fragment with clock code.

Source code in cridlib/lib.py
class CRIDMissingMediaFragmentError(CRIDError):
    """Missing media-fragment with clock code."""

CRIDSchemeAuthorityMismatchError

Bases: CRIDError

Hostname part of URI does not match 'rabe.ch'.

Source code in cridlib/lib.py
class CRIDSchemeAuthorityMismatchError(CRIDError):
    """Hostname part of URI does not match 'rabe.ch'."""

CRIDSchemeMismatchError

Bases: CRIDError

Scheme in URI does not match 'crid'.

Source code in cridlib/lib.py
class CRIDSchemeMismatchError(CRIDError):
    """Scheme in URI does not match 'crid'."""

CRIDUnsupportedVersionError

Bases: CRIDError

Unsupported version in path of URI.

Source code in cridlib/lib.py
class CRIDUnsupportedVersionError(CRIDError):
    """Unsupported version in path of URI."""

canonicalize_show(show)

Get the slug for a show.

Uses python-slugify.


show: Name of show with non-ascii chars.

slugified show name.
Source code in cridlib/lib.py
def canonicalize_show(show: str) -> str:
    """Get the slug for a show.

    Uses [python-slugify](https://github.com/un33k/python-slugify).

    Args:
    ----
        show: Name of show with non-ascii chars.

    Returns:
    -------
        slugified show name.

    """
    return slugify(show)