added filter framework, migrated to processor package
This commit is contained in:
parent
20090d14b5
commit
36e20d8ec3
@ -4,9 +4,9 @@ from spotframework.net.user import NetworkUser
|
|||||||
import spotframework.io.json as json
|
import spotframework.io.json as json
|
||||||
import spotframework.util.monthstrings as monthstrings
|
import spotframework.util.monthstrings as monthstrings
|
||||||
from spotframework.engine.playlistengine import PlaylistEngine
|
from spotframework.engine.playlistengine import PlaylistEngine
|
||||||
from spotframework.engine.filter.shuffle import Shuffle
|
from spotframework.engine.processor.shuffle import Shuffle
|
||||||
from spotframework.engine.filter.sort import SortReleaseDate
|
from spotframework.engine.processor.sort import SortReleaseDate
|
||||||
from spotframework.engine.filter.deduplicate import DeduplicateByID, DeduplicateByName
|
from spotframework.engine.processor.deduplicate import DeduplicateByID, DeduplicateByName
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import datetime
|
import datetime
|
||||||
|
@ -1,47 +0,0 @@
|
|||||||
from abc import ABC, abstractmethod
|
|
||||||
from typing import List
|
|
||||||
from spotframework.model.track import Track
|
|
||||||
|
|
||||||
|
|
||||||
class AbstractProcessor(ABC):
|
|
||||||
|
|
||||||
def __init__(self, names: List[str] = None):
|
|
||||||
self.playlist_names = names
|
|
||||||
|
|
||||||
def has_targets(self):
|
|
||||||
if self.playlist_names:
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def process(self, tracks: List[Track]):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class AbstractTestFilter(AbstractProcessor, ABC):
|
|
||||||
|
|
||||||
def __init__(self,
|
|
||||||
names: List[str] = None,
|
|
||||||
keep_failed: bool = True):
|
|
||||||
super().__init__(names)
|
|
||||||
self.keep_failed = keep_failed
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def logic_test(self, track: Track):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def process(self, tracks: List[Track]):
|
|
||||||
|
|
||||||
return_tracks = []
|
|
||||||
malformed_tracks = []
|
|
||||||
|
|
||||||
for track in tracks:
|
|
||||||
if self.logic_test(track):
|
|
||||||
return_tracks.append(track)
|
|
||||||
else:
|
|
||||||
malformed_tracks.append(track)
|
|
||||||
if self.keep_failed:
|
|
||||||
return_tracks += malformed_tracks
|
|
||||||
|
|
||||||
return return_tracks
|
|
@ -1,47 +0,0 @@
|
|||||||
from abc import ABC, abstractmethod
|
|
||||||
from .abstract import AbstractProcessor
|
|
||||||
import datetime
|
|
||||||
from typing import List
|
|
||||||
from spotframework.model.track import Track, PlaylistTrack
|
|
||||||
|
|
||||||
|
|
||||||
class Added(AbstractProcessor, ABC):
|
|
||||||
|
|
||||||
def __init__(self,
|
|
||||||
boundary: datetime.datetime,
|
|
||||||
names: List[str] = None,
|
|
||||||
keep_malformed_type: bool = True):
|
|
||||||
super().__init__(names)
|
|
||||||
self.boundary = boundary
|
|
||||||
self.keep_malformed_type = keep_malformed_type
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def check_date(self, track: PlaylistTrack):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def process(self, tracks: List[Track]):
|
|
||||||
|
|
||||||
return_tracks = []
|
|
||||||
malformed_tracks = []
|
|
||||||
|
|
||||||
for track in tracks:
|
|
||||||
if isinstance(track, PlaylistTrack):
|
|
||||||
if self.check_date(track):
|
|
||||||
return_tracks.append(track)
|
|
||||||
else:
|
|
||||||
malformed_tracks.append(track)
|
|
||||||
|
|
||||||
if self.keep_malformed_type:
|
|
||||||
return_tracks += malformed_tracks
|
|
||||||
|
|
||||||
return return_tracks
|
|
||||||
|
|
||||||
|
|
||||||
class AddedBefore(Added):
|
|
||||||
def check_date(self, track: PlaylistTrack):
|
|
||||||
return track.added_at < self.boundary
|
|
||||||
|
|
||||||
|
|
||||||
class AddedSince(Added):
|
|
||||||
def check_date(self, track: PlaylistTrack):
|
|
||||||
return track.added_at > self.boundary
|
|
@ -1,45 +0,0 @@
|
|||||||
from spotframework.engine.filter.abstract import AbstractProcessor
|
|
||||||
from typing import List
|
|
||||||
from spotframework.model.track import Track, SpotifyTrack
|
|
||||||
|
|
||||||
|
|
||||||
class DeduplicateByID(AbstractProcessor):
|
|
||||||
|
|
||||||
def __init__(self,
|
|
||||||
names: List[str] = None,
|
|
||||||
keep_malformed_type: bool = True):
|
|
||||||
super().__init__(names)
|
|
||||||
self.keep_malformed_type = keep_malformed_type
|
|
||||||
|
|
||||||
def process(self, tracks: List[Track]):
|
|
||||||
return_tracks = []
|
|
||||||
malformed_tracks = []
|
|
||||||
|
|
||||||
for track in tracks:
|
|
||||||
if isinstance(track, SpotifyTrack):
|
|
||||||
if track.uri not in [i.uri for i in return_tracks]:
|
|
||||||
return_tracks.append(track)
|
|
||||||
else:
|
|
||||||
malformed_tracks.append(track)
|
|
||||||
|
|
||||||
if self.keep_malformed_type:
|
|
||||||
return_tracks += malformed_tracks
|
|
||||||
|
|
||||||
return return_tracks
|
|
||||||
|
|
||||||
|
|
||||||
class DeduplicateByName(AbstractProcessor):
|
|
||||||
|
|
||||||
def process(self, tracks: List[Track]):
|
|
||||||
return_tracks = []
|
|
||||||
|
|
||||||
for to_check in tracks:
|
|
||||||
|
|
||||||
for cache_track in return_tracks:
|
|
||||||
if to_check.name.lower() == cache_track.name.lower():
|
|
||||||
if to_check.artists[0].name.lower() == cache_track.artists[0].name.lower():
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
return_tracks.append(to_check)
|
|
||||||
|
|
||||||
return return_tracks
|
|
@ -1,38 +0,0 @@
|
|||||||
from spotframework.engine.filter.abstract import AbstractProcessor
|
|
||||||
from typing import List
|
|
||||||
from spotframework.model.track import Track, SpotifyTrack
|
|
||||||
|
|
||||||
|
|
||||||
class SortPopularity(AbstractProcessor):
|
|
||||||
|
|
||||||
def __init__(self,
|
|
||||||
names: List[str] = None,
|
|
||||||
keep_malformed_type: bool = True):
|
|
||||||
super().__init__(names)
|
|
||||||
self.keep_malformed_type = keep_malformed_type
|
|
||||||
|
|
||||||
def sort(self, tracks: List[SpotifyTrack]):
|
|
||||||
tracks.sort(key=lambda x: x.popularity, reverse=True)
|
|
||||||
|
|
||||||
def process(self, tracks: List[Track]):
|
|
||||||
return_tracks = []
|
|
||||||
malformed_tracks = []
|
|
||||||
|
|
||||||
for track in tracks:
|
|
||||||
if isinstance(track, SpotifyTrack):
|
|
||||||
return_tracks.append(track)
|
|
||||||
else:
|
|
||||||
malformed_tracks.append(track)
|
|
||||||
|
|
||||||
self.sort(return_tracks)
|
|
||||||
|
|
||||||
if self.keep_malformed_type:
|
|
||||||
return_tracks += malformed_tracks
|
|
||||||
|
|
||||||
return return_tracks
|
|
||||||
|
|
||||||
|
|
||||||
class SortReversePopularity(SortPopularity):
|
|
||||||
|
|
||||||
def sort(self, tracks: List[SpotifyTrack]):
|
|
||||||
tracks.sort(key=lambda x: x.popularity, reverse=False)
|
|
@ -3,13 +3,13 @@ import os
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
import spotframework.util.monthstrings as monthstrings
|
import spotframework.util.monthstrings as monthstrings
|
||||||
from spotframework.engine.filter.added import AddedSince
|
from spotframework.engine.processor.added import AddedSince
|
||||||
|
|
||||||
from typing import List
|
from typing import List
|
||||||
from spotframework.model.track import SpotifyTrack
|
from spotframework.model.track import SpotifyTrack
|
||||||
from spotframework.model.playlist import SpotifyPlaylist
|
from spotframework.model.playlist import SpotifyPlaylist
|
||||||
from spotframework.net.network import Network
|
from spotframework.net.network import Network
|
||||||
from spotframework.engine.filter.abstract import AbstractProcessor
|
from spotframework.engine.processor.abstract import AbstractProcessor
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
71
spotframework/engine/processor/abstract.py
Normal file
71
spotframework/engine/processor/abstract.py
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
from abc import ABC, abstractmethod
|
||||||
|
from typing import List
|
||||||
|
from spotframework.model.track import Track
|
||||||
|
|
||||||
|
|
||||||
|
class AbstractProcessor(ABC):
|
||||||
|
|
||||||
|
def __init__(self, names: List[str] = None):
|
||||||
|
self.playlist_names = names
|
||||||
|
|
||||||
|
def has_targets(self):
|
||||||
|
if self.playlist_names:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def process(self, tracks: List[Track]):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class BatchSingleProcessor(AbstractProcessor, ABC):
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def process_single(track: Track):
|
||||||
|
return track
|
||||||
|
|
||||||
|
def process_batch(self, tracks: List[Track]):
|
||||||
|
processed = []
|
||||||
|
|
||||||
|
for track in tracks:
|
||||||
|
processed_track = self.process_single(track)
|
||||||
|
processed.append(processed_track)
|
||||||
|
|
||||||
|
return processed
|
||||||
|
|
||||||
|
def process(self, tracks: List[Track]):
|
||||||
|
return [i for i in self.process_batch(tracks) if i]
|
||||||
|
|
||||||
|
|
||||||
|
class BatchSingleTypeAwareProcessor(BatchSingleProcessor, ABC):
|
||||||
|
|
||||||
|
def __init__(self,
|
||||||
|
names: List[str] = None,
|
||||||
|
instance_check=None,
|
||||||
|
append_malformed: bool = True):
|
||||||
|
super().__init__(names)
|
||||||
|
self.instance_check = instance_check
|
||||||
|
self.append_malformed = append_malformed
|
||||||
|
|
||||||
|
def process(self, tracks: List[Track]):
|
||||||
|
|
||||||
|
if self.instance_check:
|
||||||
|
return_tracks = []
|
||||||
|
malformed_tracks = []
|
||||||
|
|
||||||
|
for track in tracks:
|
||||||
|
|
||||||
|
if isinstance(track, self.instance_check):
|
||||||
|
return_tracks.append(track)
|
||||||
|
else:
|
||||||
|
malformed_tracks.append(track)
|
||||||
|
|
||||||
|
return_tracks = super().process(return_tracks)
|
||||||
|
|
||||||
|
if self.append_malformed:
|
||||||
|
return_tracks += malformed_tracks
|
||||||
|
|
||||||
|
return return_tracks
|
||||||
|
else:
|
||||||
|
return tracks
|
28
spotframework/engine/processor/added.py
Normal file
28
spotframework/engine/processor/added.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
from .abstract import BatchSingleTypeAwareProcessor
|
||||||
|
import datetime
|
||||||
|
from typing import List
|
||||||
|
from spotframework.model.track import PlaylistTrack
|
||||||
|
|
||||||
|
|
||||||
|
class Added(BatchSingleTypeAwareProcessor):
|
||||||
|
|
||||||
|
def __init__(self,
|
||||||
|
boundary: datetime.datetime,
|
||||||
|
names: List[str] = None,
|
||||||
|
append_malformed: bool = True):
|
||||||
|
super().__init__(names,
|
||||||
|
instance_check=PlaylistTrack,
|
||||||
|
append_malformed=append_malformed)
|
||||||
|
self.boundary = boundary
|
||||||
|
|
||||||
|
|
||||||
|
class AddedBefore(Added):
|
||||||
|
def process_single(self, track: PlaylistTrack):
|
||||||
|
if track.added_at < self.boundary:
|
||||||
|
return track
|
||||||
|
|
||||||
|
|
||||||
|
class AddedSince(Added):
|
||||||
|
def process_single(self, track: PlaylistTrack):
|
||||||
|
if track.added_at > self.boundary:
|
||||||
|
return track
|
39
spotframework/engine/processor/deduplicate.py
Normal file
39
spotframework/engine/processor/deduplicate.py
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
from spotframework.engine.processor.abstract import BatchSingleProcessor, BatchSingleTypeAwareProcessor
|
||||||
|
from typing import List
|
||||||
|
from spotframework.model.track import Track, SpotifyTrack
|
||||||
|
|
||||||
|
|
||||||
|
class DeduplicateByID(BatchSingleTypeAwareProcessor):
|
||||||
|
|
||||||
|
def __init__(self,
|
||||||
|
names: List[str] = None,
|
||||||
|
append_malformed: bool = True):
|
||||||
|
super().__init__(names,
|
||||||
|
instance_check=SpotifyTrack,
|
||||||
|
append_malformed=append_malformed)
|
||||||
|
|
||||||
|
def process_batch(self, tracks: List[SpotifyTrack]):
|
||||||
|
return_tracks = []
|
||||||
|
|
||||||
|
for track in tracks:
|
||||||
|
if track.uri not in [i.uri for i in return_tracks]:
|
||||||
|
return_tracks.append(track)
|
||||||
|
|
||||||
|
return return_tracks
|
||||||
|
|
||||||
|
|
||||||
|
class DeduplicateByName(BatchSingleProcessor):
|
||||||
|
|
||||||
|
def process_batch(self, tracks: List[Track]):
|
||||||
|
return_tracks = []
|
||||||
|
|
||||||
|
for to_check in tracks:
|
||||||
|
|
||||||
|
for cache_track in return_tracks:
|
||||||
|
if to_check.name.lower() == cache_track.name.lower():
|
||||||
|
if to_check.artists[0].name.lower() == cache_track.artists[0].name.lower():
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
return_tracks.append(to_check)
|
||||||
|
|
||||||
|
return return_tracks
|
19
spotframework/engine/processor/popularity.py
Normal file
19
spotframework/engine/processor/popularity.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
from spotframework.engine.processor.abstract import BatchSingleTypeAwareProcessor
|
||||||
|
from typing import List
|
||||||
|
from spotframework.model.track import SpotifyTrack
|
||||||
|
|
||||||
|
|
||||||
|
class SortPopularity(BatchSingleTypeAwareProcessor):
|
||||||
|
|
||||||
|
def __init__(self,
|
||||||
|
names: List[str] = None,
|
||||||
|
append_malformed: bool = True,
|
||||||
|
reverse: bool = False):
|
||||||
|
super().__init__(names,
|
||||||
|
instance_check=SpotifyTrack,
|
||||||
|
append_malformed=append_malformed)
|
||||||
|
self.reverse = reverse
|
||||||
|
|
||||||
|
def process_batch(self, tracks: List[SpotifyTrack]):
|
||||||
|
tracks.sort(key=lambda x: x.popularity, reverse=self.reverse)
|
||||||
|
return tracks
|
Loading…
Reference in New Issue
Block a user