Skip to content

Commit

Permalink
docs: use proper(ish) pydocstyle annotations for mkdocs (#43)
Browse files Browse the repository at this point in the history
  • Loading branch information
hairmare authored Feb 18, 2023
1 parent af5a190 commit b73543e
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 52 deletions.
29 changes: 18 additions & 11 deletions cridlib/get.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
"""Main "get" interface for RaBe CRID's."""

from datetime import datetime, timezone
from typing import Optional

from .lib import CRID, canonicalize_show
from .strategy import future, now, past


def get(timestamp=None, fragment="") -> CRID:
def get(timestamp: Optional[datetime] = None, fragment: str = "") -> CRID:
"""Get a RaBe CRID.
If you need to get the CRID for a specific point in RaBe time using a human-readable timezone:
Examples:
You can get a CRID for a specific time.
```python
>>> from datetime import datetime
>>> from pytz import timezone
>>> crid = get(datetime(2020, 3, 1, 00, 00, tzinfo=timezone('Europe/Zurich')))
>>> print(f"version: {crid.version}, start: {crid.start}")
version: v1, start: ...
```python
>>> from datetime import datetime
>>> from pytz import timezone
>>> crid = get(datetime(2020, 3, 1, 00, 00, tzinfo=timezone('Europe/Zurich')))
>>> print(f"version: {crid.version}, start: {crid.start}")
version: v1, start: ...
```
```
Parameters:
timestamp: Exact time you want a CRID for.
If left empty, a CRID for the current time is generated.
fragment: Optional fragment to add to the end of the CRID.
Returns:
CRID: The generated CRID.
"""
_now = datetime.now(timezone.utc)
_ts = timestamp or _now
Expand Down
96 changes: 68 additions & 28 deletions cridlib/lib.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
"""Low-level cridlib implemenetation bits."""

from datetime import datetime
from pathlib import PurePath
from typing import Optional
Expand All @@ -9,8 +7,14 @@
from uritools import uricompose, urisplit # type: ignore


def canonicalize_show(show: str):
"""Get the slug for a show using python-slugify."""
def canonicalize_show(show: str) -> str:
"""Get the slug for a show using [python-slugify](https://github.com/un33k/python-slugify).
Parameters:
show: Name of show with non-ascii chars.
Returns:
slugified show name.
"""
return slugify(show)


Expand Down Expand Up @@ -42,20 +46,40 @@ class CRIDMalformedMediaFragmentError(CRIDError):


class CRID:
"""Represent CRIDs using uri."""
"""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, _uri=None) -> None:
```
"""

def __init__(self, uri: Optional[str] = None) -> None:
"""
Parameters:
uri: CRID URL to base the new CRID off of.
"""
self._show: Optional[str] = None
self._start: Optional[datetime] = None

self._uri = urisplit(_uri)
self._uri = urisplit(uri)
if self.scheme != "crid":
raise CRIDSchemeMismatchError(self.scheme, _uri)
raise CRIDSchemeMismatchError(self.scheme, uri)
if self.authority != "rabe.ch":
raise CRIDSchemeAuthorityMismatchError(self.authority, _uri)
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)
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":
Expand All @@ -68,57 +92,73 @@ def __init__(self, _uri=None) -> None:
"%Y%m%dT%H%M%S.%fZ",
)
except KeyError as ex:
raise CRIDMissingMediaFragmentError(self.fragment, _uri) from ex
raise CRIDMissingMediaFragmentError(self.fragment, uri) from ex
except ValueError as ex: # pragma: no cover
raise CRIDMalformedMediaFragmentError(self.fragment, _uri) from ex
raise CRIDMalformedMediaFragmentError(self.fragment, uri) from ex

def __str__(self) -> str:
"""
Returns:
CRID URL rendered as string.
"""
return uricompose(*self._uri)

def __repr__(self) -> str:
"""Pretty print CRID.
```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'>
```
"""
_fqcn = f"{self.__class__.__module__}.{self.__class__.__qualname__}"
return f"<class '{_fqcn}' for '{str(self)}'>"

@property
def scheme(self) -> str:
"""Get RaBe CRID scheme."""
"""
Returns:
Scheme part of the CRID.
"""
return self._uri.scheme

@property
def authority(self) -> str:
"""Get RaBe CRID authority."""
"""
Returns:
Authority part (aka hostname) of CRID.
"""
return self._uri.authority

@property
def path(self) -> CRIDPath:
"""Get RaBe CRID path."""
"""
Returns:
Path part of CRID.
"""
return CRIDPath(self._uri.path)

@property
def fragment(self) -> str:
"""Get RaBe CRID fragment."""
"""
Returns:
Framgment part of CRID.
"""
return self._uri.fragment

@property
def version(self) -> str:
"""Get RaBe CRID version."""
"""
Returns:
Version from CRIDs path.
"""
return self._version

@property
def show(self) -> Optional[str]:
"""Get RaBe CRID show."""
"""
Returns:
Show slug from CRIDs path.
"""
return self._show

@property
def start(self) -> Optional[datetime]:
"""Get RaBe CRID start time."""
"""
Returns:
Start time form CRIDs media fragment.
"""
return self._start
10 changes: 7 additions & 3 deletions cridlib/parse.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
"""Parse RaBe CRID's."""

from .lib import CRID


def parse(value: str) -> CRID:
"""Get CRID dataclass from CRID."""
"""Get CRID dataclass from CRID.
Parameters:
value: CRID URL as a string.
Returns:
CRID: The parsed CRID.
"""
return CRID(value)
2 changes: 1 addition & 1 deletion cridlib/strategy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Different strategies for getting crids from different sources.
"""Different strategies for getting CRIDs from different sources.
* [`cridlib.strategy.past`](./past/)
* [`cridlib.strategy.present`](./present/)
Expand Down
14 changes: 11 additions & 3 deletions cridlib/strategy/future.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
"""The future strategy implements getting data from LibreTime."""

from datetime import datetime, timezone
from pathlib import PurePath

Expand All @@ -12,7 +10,17 @@


def get_show(future: datetime) -> str: # pragma: no cover
"""Return the slug for a show from LibreTime if it is in the next 7 days."""
"""Return the slug for a show from LibreTime if it is in the next 7 days.
Only returns a show for the next seven days because everything futher than
that is considered unreliable as of early 2023.
Parameters:
future: Date to get the show name for.
Returns:
Name of the show scheduled for `future`.
"""

_resp = requests.get(
__LIBRETIME_INFOV2_URL,
Expand Down
10 changes: 7 additions & 3 deletions cridlib/strategy/now.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
"""The now strategy implements getting data from Songticker."""

import xml.etree.ElementTree as ET
from pathlib import PurePath

Expand All @@ -10,7 +8,13 @@


def get_show() -> str:
"""Return the currently running shows slug from nowplaying."""
"""Return the currently running show.
Calls the the [nowplaying](https://github.com/radiorabe/nowplaying) songticker's API.
Returns:
Name of the currently running show.
"""

_resp = requests.get(__SONGTICKER_URL, timeout=10)
_tree = ET.fromstring(_resp.text)
Expand Down
13 changes: 10 additions & 3 deletions cridlib/strategy/past.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
"""The past strategy implements getting data from archiv.rabe.ch."""

from datetime import datetime

import requests
Expand All @@ -8,7 +6,16 @@


def get_show(past: datetime) -> str:
"""Return the a show slug from a past show."""
"""Return a show from the past.
Asks the the [raar](https://github.com/radiorabe/raar) archive for the info.
Parameters:
past: Date to get the show name for.
Returns:
Show name from the archive for `past`.
"""

_url = f"{__ARCHIV_BROADCASTS_URL}{past.year}/{past.month:02d}/{past.day:02d}/{past.hour:02d}{past.minute:02d}{past.second:02d}" # pylint: disable=line-too-long
_resp = requests.get(_url, timeout=10)
Expand Down