From d9725003c5d1e4aa683aca9e07a83b292cd61ca1 Mon Sep 17 00:00:00 2001 From: jo Date: Fri, 22 Jul 2022 15:41:38 +0200 Subject: [PATCH] feat(playout): integrate api-client v2 calls --- playout/libretime_playout/config.py | 3 +- playout/libretime_playout/main.py | 5 +- playout/libretime_playout/player/file.py | 39 +++++------- playout/libretime_playout/player/schedule.py | 12 ++-- playout/setup.py | 1 + playout/tests/player/schedule_test.py | 65 +++++++++++--------- 6 files changed, 66 insertions(+), 59 deletions(-) diff --git a/playout/libretime_playout/config.py b/playout/libretime_playout/config.py index e3ae9b618..dac238293 100644 --- a/playout/libretime_playout/config.py +++ b/playout/libretime_playout/config.py @@ -1,6 +1,6 @@ from pathlib import Path -from libretime_shared.config import BaseConfig, RabbitMQConfig +from libretime_shared.config import BaseConfig, GeneralConfig, RabbitMQConfig from pydantic import BaseModel from typing_extensions import Literal @@ -23,5 +23,6 @@ class PlayoutConfig(BaseModel): class Config(BaseConfig): + general: GeneralConfig rabbitmq: RabbitMQConfig = RabbitMQConfig() playout: PlayoutConfig = PlayoutConfig() diff --git a/playout/libretime_playout/main.py b/playout/libretime_playout/main.py index 709b20d78..9c204e4e2 100644 --- a/playout/libretime_playout/main.py +++ b/playout/libretime_playout/main.py @@ -129,7 +129,10 @@ def cli(log_level: str, log_filepath: Optional[Path], config_filepath: Optional[ signal.signal(signal.SIGINT, keyboardInterruptHandler) legacy_client = LegacyClient() - api_client = ApiClient() + api_client = ApiClient( + base_url=config.general.public_url, + api_key=config.general.api_key, + ) g = Global(legacy_client) while not g.selfcheck(): diff --git a/playout/libretime_playout/player/file.py b/playout/libretime_playout/player/file.py index 499f766ff..726f9aff6 100644 --- a/playout/libretime_playout/player/file.py +++ b/playout/libretime_playout/player/file.py @@ -8,7 +8,7 @@ from threading import Thread from libretime_api_client.v2 import ApiClient from loguru import logger -from requests.exceptions import ConnectionError, Timeout +from requests.exceptions import ConnectionError, HTTPError, Timeout class PypoFile(Thread): @@ -22,11 +22,9 @@ class PypoFile(Thread): """ Copy media_item from local library directory to local cache directory. """ - src = media_item["uri"] + file_id = media_item["id"] dst = media_item["dst"] - src_size = media_item["filesize"] - dst_exists = True try: dst_size = os.path.getsize(dst) @@ -43,33 +41,26 @@ class PypoFile(Thread): # become an issue here... This needs proper cache management. # https://github.com/libretime/libretime/issues/756#issuecomment-477853018 # https://github.com/libretime/libretime/pull/845 - logger.debug( - "file %s already exists in local cache as %s, skipping copying..." - % (src, dst) - ) + logger.debug(f"found file {file_id} in cache {dst}, skipping copy...") else: do_copy = True media_item["file_ready"] = not do_copy if do_copy: - logger.info(f"copying from {src} to local cache {dst}") + logger.info(f"copying file {file_id} to cache {dst}") try: with open(dst, "wb") as handle: logger.info(media_item) - response = self.api_client.services.file_download_url( - id=media_item["id"] - ) + try: + response = self.api_client.download_file(file_id) + for chunk in response.iter_content(chunk_size=1024): + handle.write(chunk) - if not response.ok: - logger.error(response) + except HTTPError as exception: raise Exception( - "%s - Error occurred downloading file" - % response.status_code - ) - - for chunk in response.iter_content(chunk_size=1024): - handle.write(chunk) + f"could not download file {media_item['id']}" + ) from exception # make file world readable and owner writable os.chmod(dst, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH) @@ -82,7 +73,7 @@ class PypoFile(Thread): media_item["file_ready"] = True except Exception as e: - logger.error(f"Could not copy from {src} to {dst}") + logger.error(f"could not copy file {file_id} to {dst}") logger.error(e) def report_file_size_and_md5_to_api(self, file_path, file_id): @@ -109,8 +100,10 @@ class PypoFile(Thread): "Could not update media file %s with file size and md5 hash:" % file_id ) try: - payload = {"filesize": file_size, "md5": md5_hash} - response = self.api_client.update_file(file_id, payload) + self.api_client.update_file( + file_id, + json={"filesize": file_size, "md5": md5_hash}, + ) except (ConnectionError, Timeout): logger.error(error_msg) except Exception as e: diff --git a/playout/libretime_playout/player/schedule.py b/playout/libretime_playout/player/schedule.py index 01d3bd328..8ccad0ec7 100644 --- a/playout/libretime_playout/player/schedule.py +++ b/playout/libretime_playout/player/schedule.py @@ -25,29 +25,29 @@ def get_schedule(api_client: ApiClient): current_time_str = current_time.isoformat(timespec="seconds") end_time_str = end_time.isoformat(timespec="seconds") - schedule = api_client.services.schedule_url( + schedule = api_client.list_schedule( params={ "ends_after": f"{current_time_str}Z", "ends_before": f"{end_time_str}Z", "overbooked": False, "position_status__gt": 0, } - ) + ).json() events = {} for item in schedule: item["starts_at"] = isoparse(item["starts_at"]) item["ends_at"] = isoparse(item["ends_at"]) - show_instance = api_client.services.show_instance_url(id=item["instance_id"]) - show = api_client.services.show_url(id=show_instance["show_id"]) + show_instance = api_client.get_show_instance(item["instance_id"]).json() + show = api_client.get_show(show_instance["show_id"]).json() if item["file"]: - file = api_client.services.file_url(id=item["file_id"]) + file = api_client.get_file(item["file_id"]).json() events.update(generate_file_events(item, file, show)) elif item["stream"]: - webstream = api_client.services.webstream_url(id=item["stream_id"]) + webstream = api_client.get_webstream(item["stream_id"]).json() events.update(generate_webstream_events(item, webstream, show)) return {"media": events} diff --git a/playout/setup.py b/playout/setup.py index d27aac764..5cc6686b3 100644 --- a/playout/setup.py +++ b/playout/setup.py @@ -40,6 +40,7 @@ setup( extras_require={ "dev": [ "distro", + "requests-mock", f"libretime-api-client @ file://localhost{here.parent / 'api-client'}", f"libretime-shared @ file://localhost{here.parent / 'shared'}", ], diff --git a/playout/tests/player/schedule_test.py b/playout/tests/player/schedule_test.py index 688f31201..821618b98 100644 --- a/playout/tests/player/schedule_test.py +++ b/playout/tests/player/schedule_test.py @@ -1,10 +1,17 @@ +import pytest +from libretime_api_client.v2 import ApiClient + from libretime_playout.player.schedule import get_schedule -class ApiClientServicesMock: - @staticmethod - def schedule_url(*args, **kwargs): - return [ +@pytest.fixture(name="api_client_mock") +def _api_client_mock(requests_mock): + base_url = "http://localhost" + api_client = ApiClient(base_url=base_url, api_key="test_key") + + requests_mock.get( + f"{base_url}/api/v2/schedule", + json=[ { "id": 17, "starts_at": "2022-03-04T15:30:00Z", @@ -31,23 +38,26 @@ class ApiClientServicesMock: "cue_out": "00:30:00", "instance_id": 3, }, - ] + ], + ) - @staticmethod - def show_instance_url(*args, **kwargs): - return { + requests_mock.get( + f"{base_url}/api/v2/show-instances/3", + json={ "show_id": 3, - } + }, + ) - @staticmethod - def show_url(*args, **kwargs): - return { + requests_mock.get( + f"{base_url}/api/v2/shows/3", + json={ "name": "Test", - } + }, + ) - @staticmethod - def file_url(*args, **kwargs): - return { + requests_mock.get( + f"{base_url}/api/v2/files/1", + json={ "id": 1, "url": None, "replay_gain": "-8.77", @@ -55,24 +65,23 @@ class ApiClientServicesMock: "artist_name": "Bag Raiders", "track_title": "Shooting Stars", "mime": "audio/mp3", - } + }, + ) - @staticmethod - def webstream_url(*args, **kwargs): - return { + requests_mock.get( + f"{base_url}/api/v2/webstreams/1", + json={ "id": 1, "name": "Test", "url": "http://some-other-radio:8800/main.ogg", - } + }, + ) + + return api_client -class ApiClientMock: - services = ApiClientServicesMock() - - -def test_get_schedule(): - api_client = ApiClientMock() - assert get_schedule(api_client) == { +def test_get_schedule(api_client_mock: ApiClient): + assert get_schedule(api_client_mock) == { "media": { "2022-03-04-15-30-00": { "type": "file",