refactor(analyzer): improve analyzer pipeline module (#1542)

* rename steps to pipeline module

* move pipeline entrypoint to pipeline module

* rename steps test module to pipeline

* fix paths after renames

* move step protocol to pipeline

* create pipeline status enum

* use Protocol from typing extensions

* Fix linting
This commit is contained in:
Jonas L 2022-01-28 06:09:19 +01:00 committed by GitHub
parent 74c8d20284
commit cba905e367
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 34 additions and 26 deletions

View File

@ -8,7 +8,7 @@ import pika
from libretime_shared.config import RabbitMQConfig from libretime_shared.config import RabbitMQConfig
from loguru import logger from loguru import logger
from .pipeline import Pipeline from .pipeline import Pipeline, PipelineStatus
from .status_reporter import StatusReporter from .status_reporter import StatusReporter
EXCHANGE = "airtime-uploads" EXCHANGE = "airtime-uploads"
@ -265,7 +265,7 @@ class MessageListener:
metadata = q.get() metadata = q.get()
except Exception as e: except Exception as e:
logger.error("Analyzer pipeline exception: %s" % str(e)) logger.error("Analyzer pipeline exception: %s" % str(e))
metadata["import_status"] = Pipeline.IMPORT_STATUS_FAILED metadata["import_status"] = PipelineStatus.failed
# Ensure our queue doesn't fill up and block due to unexpected behaviour. Defensive code. # Ensure our queue doesn't fill up and block due to unexpected behaviour. Defensive code.
while not q.empty(): while not q.empty():

View File

@ -0,0 +1 @@
from .pipeline import Pipeline, PipelineStatus

View File

@ -1,14 +1,29 @@
""" Analyzes and imports an audio file into the Airtime library. """ Analyzes and imports an audio file into the Airtime library.
""" """
from enum import Enum
from queue import Queue from queue import Queue
from typing import Any, Dict
from loguru import logger from loguru import logger
from typing_extensions import Protocol
from .steps.analyze_cuepoint import analyze_cuepoint from .analyze_cuepoint import analyze_cuepoint
from .steps.analyze_metadata import analyze_metadata from .analyze_metadata import analyze_metadata
from .steps.analyze_playability import UnplayableFileError, analyze_playability from .analyze_playability import UnplayableFileError, analyze_playability
from .steps.analyze_replaygain import analyze_replaygain from .analyze_replaygain import analyze_replaygain
from .steps.organise_file import organise_file from .organise_file import organise_file
class Step(Protocol):
@staticmethod
def __call__(filename: str, metadata: Dict[str, Any]):
...
class PipelineStatus(int, Enum):
succeed = 0
pending = 1
failed = 2
class Pipeline: class Pipeline:
@ -21,8 +36,6 @@ class Pipeline:
the failure to import can be reported back to the web application. the failure to import can be reported back to the web application.
""" """
IMPORT_STATUS_FAILED = 2
@staticmethod @staticmethod
def run_analysis( def run_analysis(
queue, queue,
@ -99,7 +112,7 @@ class Pipeline:
queue.put(metadata) queue.put(metadata)
except UnplayableFileError as e: except UnplayableFileError as e:
logger.exception(e) logger.exception(e)
metadata["import_status"] = Pipeline.IMPORT_STATUS_FAILED metadata["import_status"] = PipelineStatus.failed
metadata["reason"] = "The file could not be played." metadata["reason"] = "The file could not be played."
raise e raise e
except Exception as e: except Exception as e:

View File

@ -1,7 +0,0 @@
from typing import Any, Dict, Protocol
class Step(Protocol):
@staticmethod
def __call__(filename: str, metadata: Dict[str, Any]):
...

View File

@ -21,7 +21,7 @@ setup(
license="AGPLv3", license="AGPLv3",
packages=[ packages=[
"libretime_analyzer", "libretime_analyzer",
"libretime_analyzer.steps", "libretime_analyzer.pipeline",
], ],
entry_points={ entry_points={
"console_scripts": [ "console_scripts": [
@ -34,6 +34,7 @@ setup(
"pika>=1.0.0", "pika>=1.0.0",
"file-magic", "file-magic",
"requests>=2.7.0", "requests>=2.7.0",
"typing_extensions",
], ],
extras_require={ extras_require={
"dev": [ "dev": [

View File

@ -1,6 +1,6 @@
import pytest import pytest
from libretime_analyzer.steps.analyze_cuepoint import analyze_cuepoint from libretime_analyzer.pipeline.analyze_cuepoint import analyze_cuepoint
from ..fixtures import FILES from ..fixtures import FILES

View File

@ -1,6 +1,6 @@
import pytest import pytest
from libretime_analyzer.steps.analyze_metadata import analyze_metadata from libretime_analyzer.pipeline.analyze_metadata import analyze_metadata
from ..fixtures import FILE_INVALID_DRM, FILE_INVALID_TXT, FILES_TAGGED from ..fixtures import FILE_INVALID_DRM, FILE_INVALID_TXT, FILES_TAGGED

View File

@ -3,7 +3,7 @@ from unittest.mock import patch
import distro import distro
import pytest import pytest
from libretime_analyzer.steps.analyze_playability import ( from libretime_analyzer.pipeline.analyze_playability import (
UnplayableFileError, UnplayableFileError,
analyze_playability, analyze_playability,
) )
@ -21,7 +21,7 @@ def test_analyze_playability(filepath):
def test_analyze_playability_missing_liquidsoap(): def test_analyze_playability_missing_liquidsoap():
with patch( with patch(
"libretime_analyzer.steps.analyze_playability.LIQUIDSOAP_EXECUTABLE", "libretime_analyzer.pipeline.analyze_playability.LIQUIDSOAP_EXECUTABLE",
"foobar", "foobar",
): ):
analyze_playability(str(FILES[0].path), dict()) analyze_playability(str(FILES[0].path), dict())

View File

@ -1,7 +1,7 @@
import distro import distro
import pytest import pytest
from libretime_analyzer.steps.analyze_replaygain import analyze_replaygain from libretime_analyzer.pipeline.analyze_replaygain import analyze_replaygain
from ..fixtures import FILES from ..fixtures import FILES

View File

@ -5,7 +5,7 @@ from unittest import mock
import pytest import pytest
from libretime_analyzer.steps.organise_file import organise_file from libretime_analyzer.pipeline.organise_file import organise_file
from ..conftest import AUDIO_FILENAME from ..conftest import AUDIO_FILENAME
@ -82,7 +82,7 @@ def test_organise_file_triplicate_file(src_dir, dest_dir):
# Here we use mock to patch out the time.localtime() function so that it # Here we use mock to patch out the time.localtime() function so that it
# always returns the same value. This allows us to consistently simulate this test cases # always returns the same value. This allows us to consistently simulate this test cases
# where the last two of the three files are imported at the same time as the timestamp. # where the last two of the three files are imported at the same time as the timestamp.
with mock.patch("libretime_analyzer.steps.organise_file.time") as mock_time: with mock.patch("libretime_analyzer.pipeline.organise_file.time") as mock_time:
mock_time.localtime.return_value = time.localtime() # date(2010, 10, 8) mock_time.localtime.return_value = time.localtime() # date(2010, 10, 8)
mock_time.side_effect = time.time mock_time.side_effect = time.time

View File

@ -6,7 +6,7 @@ import pytest
from libretime_analyzer.pipeline import Pipeline from libretime_analyzer.pipeline import Pipeline
from .conftest import AUDIO_FILENAME, AUDIO_IMPORT_DEST from ..conftest import AUDIO_FILENAME, AUDIO_IMPORT_DEST
def test_run_analysis(src_dir, dest_dir): def test_run_analysis(src_dir, dest_dir):