Add meta format mapper

This commit is contained in:
Joakim Soderlund 2017-11-10 23:38:49 +01:00
parent 478b2e7080
commit 4ee0824230
2 changed files with 85 additions and 3 deletions

View file

@ -24,11 +24,12 @@ Mappers for Fimfarchive.
import os
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 fimfarchive.exceptions import InvalidStoryError
from fimfarchive.flavors import MetaFormat
from fimfarchive.stories import Story
@ -115,3 +116,24 @@ class StoryPathMapper(Mapper[str]):
key = str(story.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

View file

@ -23,12 +23,16 @@ Mapper tests.
import os
from typing import no_type_check, Dict, Any
from unittest.mock import patch, MagicMock, PropertyMock
import pytest
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
@ -108,7 +112,7 @@ class TestStoryDateMapper:
"""
Tests `None` is returned when meta contains no dates.
"""
meta = {
meta: Dict[str, Any] = {
CHAPTERS: [
dict(),
dict(),
@ -259,6 +263,7 @@ class TestStoryPathMapper:
assert mapper(story) == path
@no_type_check
def test_casts_values(self, tmpdir, story):
"""
Tests casts all values to string when joining.
@ -274,3 +279,58 @@ class TestStoryPathMapper:
assert mapper(story) == os.path.join('dir', 'key')
assert directory.__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