mirror of
https://github.com/JockeTF/fimfarchive.git
synced 2024-11-22 05:17:59 +01:00
Add update stamper
This commit is contained in:
parent
0a862abcd0
commit
81c4346f10
2 changed files with 190 additions and 2 deletions
|
@ -22,16 +22,23 @@ Stampers for Fimfarchive.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict, Optional, Set, Type, TypeVar
|
||||||
|
|
||||||
|
import arrow
|
||||||
|
|
||||||
|
from fimfarchive.flavors import Flavor, UpdateStatus
|
||||||
from fimfarchive.stories import Story
|
from fimfarchive.stories import Story
|
||||||
|
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'Stamper',
|
'Stamper',
|
||||||
|
'UpdateStamper',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
F = TypeVar('F', bound=Flavor)
|
||||||
|
|
||||||
|
|
||||||
class Stamper:
|
class Stamper:
|
||||||
"""
|
"""
|
||||||
Adds archive-related information to stories.
|
Adds archive-related information to stories.
|
||||||
|
@ -62,3 +69,59 @@ class Stamper:
|
||||||
story: The story to stamp.
|
story: The story to stamp.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateStamper(Stamper):
|
||||||
|
"""
|
||||||
|
Adds modification dates to stories.
|
||||||
|
"""
|
||||||
|
spec: Dict[str, Set[UpdateStatus]] = {
|
||||||
|
'date_created': {
|
||||||
|
UpdateStatus.CREATED,
|
||||||
|
},
|
||||||
|
'date_fetched': {
|
||||||
|
UpdateStatus.CREATED,
|
||||||
|
UpdateStatus.REVIVED,
|
||||||
|
UpdateStatus.UPDATED,
|
||||||
|
},
|
||||||
|
'date_updated': {
|
||||||
|
UpdateStatus.CREATED,
|
||||||
|
UpdateStatus.UPDATED,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
def find_flavor(self, story: Story, flavor: Type[F]) -> Optional[F]:
|
||||||
|
"""
|
||||||
|
Searches for a flavor of a specific type.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
story: The story to search in.
|
||||||
|
flavor: The flavor type to find.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A flavor of the desired type, or None.
|
||||||
|
"""
|
||||||
|
for current in story.flavors:
|
||||||
|
if isinstance(current, flavor):
|
||||||
|
return current
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def __call__(self, story: Story) -> None:
|
||||||
|
"""
|
||||||
|
Applies modification dates to a story.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
story: The story to stamp.
|
||||||
|
"""
|
||||||
|
timestamp = arrow.utcnow().isoformat()
|
||||||
|
flavor = self.find_flavor(story, UpdateStatus)
|
||||||
|
archive = self.get_archive(story)
|
||||||
|
|
||||||
|
archive['date_checked'] = timestamp
|
||||||
|
|
||||||
|
for key, value in self.spec.items():
|
||||||
|
if flavor in value:
|
||||||
|
archive[key] = timestamp
|
||||||
|
elif key not in archive:
|
||||||
|
archive[key] = None
|
||||||
|
|
|
@ -22,11 +22,14 @@ Stamper tests.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
|
from unittest.mock import patch
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
||||||
|
import arrow
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from fimfarchive.stampers import Stamper
|
from fimfarchive.flavors import UpdateStatus
|
||||||
|
from fimfarchive.stampers import Stamper, UpdateStamper
|
||||||
|
|
||||||
|
|
||||||
class TestStamper:
|
class TestStamper:
|
||||||
|
@ -62,3 +65,125 @@ class TestStamper:
|
||||||
|
|
||||||
assert archive is original
|
assert archive is original
|
||||||
assert meta['archive'] is original
|
assert meta['archive'] is original
|
||||||
|
|
||||||
|
|
||||||
|
class TestUpdateStamper:
|
||||||
|
"""
|
||||||
|
UpdateStamper tests.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def time(self):
|
||||||
|
"""
|
||||||
|
Returns a timestamp for the mocked utcnow.
|
||||||
|
"""
|
||||||
|
stamp = arrow.get(1)
|
||||||
|
|
||||||
|
with patch('arrow.utcnow') as m:
|
||||||
|
m.return_value = stamp
|
||||||
|
yield stamp.isoformat()
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def stamper(self, time):
|
||||||
|
"""
|
||||||
|
Returns an update stamper instance.
|
||||||
|
"""
|
||||||
|
return UpdateStamper()
|
||||||
|
|
||||||
|
def test_created_story(self, stamper, story, time):
|
||||||
|
"""
|
||||||
|
Tests timestamps are added for created stories.
|
||||||
|
"""
|
||||||
|
story.flavors.add(UpdateStatus.CREATED)
|
||||||
|
stamper(story)
|
||||||
|
|
||||||
|
archive = story.meta['archive']
|
||||||
|
assert archive['date_checked'] == time
|
||||||
|
assert archive['date_created'] == time
|
||||||
|
assert archive['date_fetched'] == time
|
||||||
|
assert archive['date_updated'] == time
|
||||||
|
|
||||||
|
def test_updated_story(self, stamper, story, time):
|
||||||
|
"""
|
||||||
|
Tests timestamps are added for updated stories.
|
||||||
|
"""
|
||||||
|
story.flavors.add(UpdateStatus.UPDATED)
|
||||||
|
stamper(story)
|
||||||
|
|
||||||
|
archive = story.meta['archive']
|
||||||
|
assert archive['date_checked'] == time
|
||||||
|
assert archive['date_created'] is None
|
||||||
|
assert archive['date_fetched'] == time
|
||||||
|
assert archive['date_updated'] == time
|
||||||
|
|
||||||
|
def test_revived_story(self, stamper, story, time):
|
||||||
|
"""
|
||||||
|
Tests timestamps are added for revived stories.
|
||||||
|
"""
|
||||||
|
story.flavors.add(UpdateStatus.REVIVED)
|
||||||
|
stamper(story)
|
||||||
|
|
||||||
|
archive = story.meta['archive']
|
||||||
|
assert archive['date_checked'] == time
|
||||||
|
assert archive['date_created'] is None
|
||||||
|
assert archive['date_fetched'] == time
|
||||||
|
assert archive['date_updated'] is None
|
||||||
|
|
||||||
|
def test_deleted_story(self, stamper, story, time):
|
||||||
|
"""
|
||||||
|
Tests timestamps are added for deleted stories.
|
||||||
|
"""
|
||||||
|
story.flavors.add(UpdateStatus.DELETED)
|
||||||
|
stamper(story)
|
||||||
|
|
||||||
|
archive = story.meta['archive']
|
||||||
|
assert archive['date_checked'] == time
|
||||||
|
assert archive['date_created'] is None
|
||||||
|
assert archive['date_fetched'] is None
|
||||||
|
assert archive['date_updated'] is None
|
||||||
|
|
||||||
|
def test_created_modification(self, stamper, story, time):
|
||||||
|
"""
|
||||||
|
Tests existing timestamps are replaced for created stories.
|
||||||
|
"""
|
||||||
|
story.flavors.add(UpdateStatus.CREATED)
|
||||||
|
prev = arrow.get(-1).isoformat()
|
||||||
|
|
||||||
|
story.meta['archive'] = {
|
||||||
|
'date_checked': prev,
|
||||||
|
'date_created': prev,
|
||||||
|
'date_fetched': prev,
|
||||||
|
'date_updated': prev,
|
||||||
|
}
|
||||||
|
|
||||||
|
stamper(story)
|
||||||
|
assert prev != time
|
||||||
|
|
||||||
|
archive = story.meta['archive']
|
||||||
|
assert archive['date_checked'] == time
|
||||||
|
assert archive['date_created'] == time
|
||||||
|
assert archive['date_fetched'] == time
|
||||||
|
assert archive['date_updated'] == time
|
||||||
|
|
||||||
|
def test_deleted_modification(self, stamper, story, time):
|
||||||
|
"""
|
||||||
|
Tests existing timestamps are kept for deleted stories.
|
||||||
|
"""
|
||||||
|
story.flavors.add(UpdateStatus.DELETED)
|
||||||
|
prev = arrow.get(-1).isoformat()
|
||||||
|
|
||||||
|
story.meta['archive'] = {
|
||||||
|
'date_checked': prev,
|
||||||
|
'date_created': prev,
|
||||||
|
'date_fetched': prev,
|
||||||
|
'date_updated': prev,
|
||||||
|
}
|
||||||
|
|
||||||
|
stamper(story)
|
||||||
|
assert prev != time
|
||||||
|
|
||||||
|
archive = story.meta['archive']
|
||||||
|
assert archive['date_checked'] == time
|
||||||
|
assert archive['date_created'] == prev
|
||||||
|
assert archive['date_fetched'] == prev
|
||||||
|
assert archive['date_updated'] == prev
|
||||||
|
|
Loading…
Reference in a new issue