mirror of
https://github.com/JockeTF/fimfarchive.git
synced 2024-11-22 05:17:59 +01:00
Add meta format mapper
This commit is contained in:
parent
478b2e7080
commit
4ee0824230
2 changed files with 85 additions and 3 deletions
|
@ -24,11 +24,12 @@ Mappers for Fimfarchive.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from abc import abstractmethod
|
from abc import abstractmethod
|
||||||
from typing import Generic, Optional, TypeVar
|
from typing import Dict, Generic, Optional, Set, TypeVar
|
||||||
|
|
||||||
from arrow import api as arrow, Arrow
|
from arrow import api as arrow, Arrow
|
||||||
|
|
||||||
from fimfarchive.exceptions import InvalidStoryError
|
from fimfarchive.exceptions import InvalidStoryError
|
||||||
|
from fimfarchive.flavors import MetaFormat
|
||||||
from fimfarchive.stories import Story
|
from fimfarchive.stories import Story
|
||||||
|
|
||||||
|
|
||||||
|
@ -115,3 +116,24 @@ class StoryPathMapper(Mapper[str]):
|
||||||
key = str(story.key)
|
key = str(story.key)
|
||||||
|
|
||||||
return os.path.join(directory, key)
|
return os.path.join(directory, key)
|
||||||
|
|
||||||
|
|
||||||
|
class MetaFormatMapper(Mapper[Optional[MetaFormat]]):
|
||||||
|
"""
|
||||||
|
Guesses the meta format of stories.
|
||||||
|
"""
|
||||||
|
spec: Dict[MetaFormat, Set[str]] = {
|
||||||
|
MetaFormat.ALPHA: {'likes', 'dislikes', 'words'},
|
||||||
|
MetaFormat.BETA: {'num_likes', 'num_dislikes', 'num_words'},
|
||||||
|
}
|
||||||
|
|
||||||
|
def __call__(self, story: Story) -> Optional[MetaFormat]:
|
||||||
|
items = self.spec.items()
|
||||||
|
meta = set(story.meta.keys())
|
||||||
|
|
||||||
|
matches = {fmt for fmt, spec in items if spec & meta}
|
||||||
|
|
||||||
|
if len(matches) == 1:
|
||||||
|
return next(iter(matches))
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
|
@ -23,12 +23,16 @@ Mapper tests.
|
||||||
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
from typing import no_type_check, Dict, Any
|
||||||
from unittest.mock import patch, MagicMock, PropertyMock
|
from unittest.mock import patch, MagicMock, PropertyMock
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from fimfarchive.exceptions import InvalidStoryError
|
from fimfarchive.exceptions import InvalidStoryError
|
||||||
from fimfarchive.mappers import StaticMapper, StoryDateMapper, StoryPathMapper
|
from fimfarchive.flavors import MetaFormat
|
||||||
|
from fimfarchive.mappers import (
|
||||||
|
MetaFormatMapper, StaticMapper, StoryDateMapper, StoryPathMapper
|
||||||
|
)
|
||||||
from fimfarchive.stories import Story
|
from fimfarchive.stories import Story
|
||||||
|
|
||||||
|
|
||||||
|
@ -108,7 +112,7 @@ class TestStoryDateMapper:
|
||||||
"""
|
"""
|
||||||
Tests `None` is returned when meta contains no dates.
|
Tests `None` is returned when meta contains no dates.
|
||||||
"""
|
"""
|
||||||
meta = {
|
meta: Dict[str, Any] = {
|
||||||
CHAPTERS: [
|
CHAPTERS: [
|
||||||
dict(),
|
dict(),
|
||||||
dict(),
|
dict(),
|
||||||
|
@ -259,6 +263,7 @@ class TestStoryPathMapper:
|
||||||
|
|
||||||
assert mapper(story) == path
|
assert mapper(story) == path
|
||||||
|
|
||||||
|
@no_type_check
|
||||||
def test_casts_values(self, tmpdir, story):
|
def test_casts_values(self, tmpdir, story):
|
||||||
"""
|
"""
|
||||||
Tests casts all values to string when joining.
|
Tests casts all values to string when joining.
|
||||||
|
@ -274,3 +279,58 @@ class TestStoryPathMapper:
|
||||||
assert mapper(story) == os.path.join('dir', 'key')
|
assert mapper(story) == os.path.join('dir', 'key')
|
||||||
assert directory.__str__.called_once_with()
|
assert directory.__str__.called_once_with()
|
||||||
assert story.key.__str__.called_once_with()
|
assert story.key.__str__.called_once_with()
|
||||||
|
|
||||||
|
|
||||||
|
class TestMetaFormatMapper:
|
||||||
|
"""
|
||||||
|
MetaFormatMapper tests.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mapper(self):
|
||||||
|
"""
|
||||||
|
Returns a meta format mapper instance.
|
||||||
|
"""
|
||||||
|
return MetaFormatMapper()
|
||||||
|
|
||||||
|
@pytest.fixture(params=['likes', 'dislikes', 'words'])
|
||||||
|
def alpha(self, request):
|
||||||
|
"""
|
||||||
|
Returns an alpha meta key.
|
||||||
|
"""
|
||||||
|
return request.param
|
||||||
|
|
||||||
|
@pytest.fixture(params=['num_likes', 'num_dislikes', 'num_words'])
|
||||||
|
def beta(self, request):
|
||||||
|
"""
|
||||||
|
Returns a beta meta key.
|
||||||
|
"""
|
||||||
|
return request.param
|
||||||
|
|
||||||
|
def merge(self, story, *keys):
|
||||||
|
"""
|
||||||
|
Returns a story containing the requested meta keys.
|
||||||
|
"""
|
||||||
|
meta = {key: i for i, key in enumerate(keys, 1)}
|
||||||
|
return story.merge(meta=meta)
|
||||||
|
|
||||||
|
def test_alpha_format(self, mapper, story, alpha):
|
||||||
|
"""
|
||||||
|
Tests alpha meta format is detected.
|
||||||
|
"""
|
||||||
|
story = self.merge(story, alpha, 'misc')
|
||||||
|
assert mapper(story) == MetaFormat.ALPHA
|
||||||
|
|
||||||
|
def test_beta_format(self, mapper, story, beta):
|
||||||
|
"""
|
||||||
|
Tests beta meta format is detected.
|
||||||
|
"""
|
||||||
|
story = self.merge(story, beta, 'misc')
|
||||||
|
assert mapper(story) == MetaFormat.BETA
|
||||||
|
|
||||||
|
def test_conflict(self, mapper, story, alpha, beta):
|
||||||
|
"""
|
||||||
|
Tests None is returned for conflicting meta keys.
|
||||||
|
"""
|
||||||
|
story = self.merge(story, alpha, beta)
|
||||||
|
assert mapper(story) is None
|
||||||
|
|
Loading…
Reference in a new issue