cleared up a lot of boilerplate with lazy properties
This commit is contained in:
parent
206027073c
commit
6b9cf85fc5
|
@ -3,6 +3,7 @@ import os
|
|||
import mutagen
|
||||
import abc
|
||||
from media.monitor.exceptions import BadSongFile
|
||||
from media.monitor.pure import LazyProperty
|
||||
|
||||
class PathChannel(object):
|
||||
"""a dumb struct; python has no record types"""
|
||||
|
@ -18,32 +19,21 @@ class HasMetaData(object):
|
|||
__metaclass__ = abc.ABCMeta
|
||||
# doing weird bullshit here because python constructors only
|
||||
# call the constructor of the leftmost superclass.
|
||||
@property
|
||||
@LazyProperty
|
||||
def metadata(self):
|
||||
# Normally this would go in init but we don't like
|
||||
# relying on consumers of this behaviour to have to call
|
||||
# the constructor
|
||||
if not hasattr(self,"_loaded"): self._loaded = False
|
||||
if self._loaded: return self._metadata
|
||||
else:
|
||||
f = None
|
||||
try: f = mutagen.File(self.path, easy=True)
|
||||
except Exception: raise BadSongFile(self.path)
|
||||
# value returned by mutagen only acts like a dictionary.
|
||||
# in fact it comes with a nice surprise for you if you try
|
||||
# to add elements to it
|
||||
self._metadata = {}
|
||||
for k,v in f:
|
||||
if isinstance(v, list):
|
||||
if len(v) == 1:
|
||||
self._metadata[k] = v[0]
|
||||
else:
|
||||
raise Exception("Weird mutagen %s:%s" % (k,str(v)))
|
||||
else:
|
||||
self._metadata[k] = v
|
||||
self._loaded = True
|
||||
return self.metadata
|
||||
|
||||
try: f = mutagen.File(self.path, easy=True)
|
||||
except Exception: raise BadSongFile(self.path)
|
||||
metadata = {}
|
||||
for k,v in f:
|
||||
# Special handling of attributes here
|
||||
if isinstance(v, list):
|
||||
if len(v) == 1: metadata[k] = v[0]
|
||||
else: raise Exception("Weird mutagen %s:%s" % (k,str(v)))
|
||||
else: metadata[k] = v
|
||||
return metadata
|
||||
|
||||
class BaseEvent(object):
|
||||
__metaclass__ = abc.ABCMeta
|
||||
|
|
|
@ -10,6 +10,12 @@ class Handles(object):
|
|||
@abc.abstractmethod
|
||||
def handle(self, sender, event, *args, **kwargs): pass
|
||||
|
||||
|
||||
# TODO : remove the code duplication between ReportHandler and
|
||||
# ProblemFileHandler. Namely the part where both initialize pydispatch
|
||||
# TODO : Investigate whether weak reffing in dispatcher.connect could possibly
|
||||
# cause a memory leak
|
||||
|
||||
class ReportHandler(Handles):
|
||||
__metaclass__ = abc.ABCMeta
|
||||
def __init__(self, signal):
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
import logging
|
||||
import abc
|
||||
from media.monitor.pure import LazyProperty
|
||||
|
||||
logger = logging.getLogger('mediamonitor2')
|
||||
logging.basicConfig(filename='/home/rudi/throwaway/mm2.log', level=logging.DEBUG)
|
||||
|
||||
class Loggable(object):
|
||||
__metaclass__ = abc.ABCMeta
|
||||
@property
|
||||
# TODO : replace this boilerplate with LazyProperty
|
||||
@LazyProperty
|
||||
def logger(self):
|
||||
if not hasattr(self,"_logger"): self._logger = logging.getLogger('mediamonitor2')
|
||||
return self._logger
|
||||
|
|
|
@ -5,6 +5,21 @@ import shutil
|
|||
supported_extensions = ["mp3", "ogg"]
|
||||
unicode_unknown = u'unknown'
|
||||
|
||||
class LazyProperty(object):
|
||||
"""
|
||||
meant to be used for lazy evaluation of an object attribute.
|
||||
property should represent non-mutable data, as it replaces itself.
|
||||
"""
|
||||
def __init__(self,fget):
|
||||
self.fget = fget
|
||||
self.func_name = fget.__name__
|
||||
|
||||
def __get__(self,obj,cls):
|
||||
if obj is None: return None
|
||||
value = self.fget(obj)
|
||||
setattr(obj,self.func_name,value)
|
||||
return value
|
||||
|
||||
class IncludeOnly(object):
|
||||
"""
|
||||
A little decorator to help listeners only be called on extensions they support
|
||||
|
|
|
@ -7,7 +7,10 @@ from media.monitor.handler import ReportHandler
|
|||
from media.monitor.events import NewFile, DeleteFile
|
||||
from media.monitor.log import Loggable
|
||||
from media.monitor.exceptions import BadSongFile
|
||||
from media.monitor.airtime import Request
|
||||
import media.monitor.pure as mmp
|
||||
from media.monitor.pure import LazyProperty
|
||||
|
||||
import api_clients.api_client as ac
|
||||
|
||||
class RequestSync(threading.Thread,Loggable):
|
||||
def __init__(self, watcher, requests):
|
||||
|
@ -15,11 +18,14 @@ class RequestSync(threading.Thread,Loggable):
|
|||
self.watcher = watcher
|
||||
self.requests = requests
|
||||
|
||||
@LazyProperty
|
||||
def apiclient(self):
|
||||
return ac.AirTimeApiClient()
|
||||
|
||||
def run(self):
|
||||
# TODO : implement proper request sending
|
||||
self.logger.info("launching request with %d items." % len(self.requests))
|
||||
try: Request.serialize(self.requests).send()
|
||||
except: self.logger.info("Failed to send request...")
|
||||
# self.apiclient.update_media_metadata(self
|
||||
self.watcher.flag_done()
|
||||
|
||||
class TimeoutWatcher(threading.Thread,Loggable):
|
||||
|
@ -55,6 +61,7 @@ class WatchSyncer(ReportHandler,Loggable):
|
|||
# trying to send the http requests in order
|
||||
self.__requests = []
|
||||
self.request_running = False
|
||||
# we don't actually use this "private" instance variable anywhere
|
||||
self.__current_thread = None
|
||||
tc = TimeoutWatcher(self, timeout)
|
||||
tc.daemon = True
|
||||
|
|
|
@ -6,8 +6,7 @@ from media.monitor.organizer import Organizer
|
|||
from media.monitor.events import PathChannel
|
||||
from media.monitor.watchersyncer import WatchSyncer
|
||||
from media.monitor.handler import ProblemFileHandler
|
||||
from media.monitor.bootstrap import Bootstrapper
|
||||
from media.monitor.airtime import DBDumper, Connection
|
||||
#from media.monitor.bootstrap import Bootstrapper
|
||||
|
||||
channels = {
|
||||
# note that org channel still has a 'watch' path because that is the path
|
||||
|
@ -22,11 +21,11 @@ org = Organizer(channel=channels['org'],target_path=channels['watch'].path)
|
|||
watch = WatchSyncer(channel=channels['watch'])
|
||||
problem_files = ProblemFileHandler(channel=channels['badfile'])
|
||||
# do the bootstrapping before any listening is going one
|
||||
conn = Connection('localhost', 'more', 'shit', 'here')
|
||||
db = DBDumper(conn).dump_block()
|
||||
bs = Bootstrapper(db, [channels['org']], [channels['watch']])
|
||||
bs.flush_organize()
|
||||
bs.flush_watch()
|
||||
#conn = Connection('localhost', 'more', 'shit', 'here')
|
||||
#db = DBDumper(conn).dump_block()
|
||||
#bs = Bootstrapper(db, [channels['org']], [channels['watch']])
|
||||
#bs.flush_organize()
|
||||
#bs.flush_watch()
|
||||
|
||||
wm = pyinotify.WatchManager()
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 0653ec0b89362921f075af96ee8772538b801a7c
|
||||
Subproject commit 492242f4bb7367afebbf2f096067cb5a5d3c0449
|
Loading…
Reference in New Issue