Added api and front_end as Modules
This commit is contained in:
1 parent
09135e1738
commit
38a9ae2592
13 files changed
+76
-24
No files matched your search
@@ -0,0 +1,83 @@
|
||||
from __future__ import with_statement
|
||||
from blinker import signal, Signal
|
||||
from couchpotato.core.logger import CPLog
|
||||
import ConfigParser
|
||||
import os.path
|
||||
import time
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
class Settings():
|
||||
|
||||
on_save = Signal()
|
||||
on_register = Signal()
|
||||
|
||||
bool = {'true':True, 'false':False}
|
||||
|
||||
def __init__(self, file):
|
||||
self.file = file
|
||||
|
||||
self.p = ConfigParser.RawConfigParser()
|
||||
self.p.read(file)
|
||||
|
||||
# Connect signals
|
||||
signal('settings.register').connect(self.registerDefaults)
|
||||
signal('settings.save').connect(self.save)
|
||||
|
||||
def parser(self):
|
||||
return self.p
|
||||
|
||||
def sections(self):
|
||||
return self.s
|
||||
|
||||
def registerDefaults(self, section_name, options = {}, save = True):
|
||||
|
||||
self.addSection(section_name)
|
||||
for option, value in options.iteritems():
|
||||
self.setDefault(section_name, option, value)
|
||||
|
||||
log.debug('Defaults for "%s": %s' % (section_name, options))
|
||||
self.on_register.send(self)
|
||||
|
||||
if save:
|
||||
self.save(self)
|
||||
|
||||
def set(self, section, option, value):
|
||||
return self.p.set(section, option, value)
|
||||
|
||||
def get(self, option = '', section = 'global', default = ''):
|
||||
|
||||
try:
|
||||
value = self.p.get(section, option)
|
||||
|
||||
if(self.is_int(value)):
|
||||
return int(value)
|
||||
|
||||
if str(value).lower() in self.bool:
|
||||
return self.bool.get(str(value).lower())
|
||||
|
||||
return value if type(value) != str else value.strip()
|
||||
except:
|
||||
return default
|
||||
|
||||
def save(self, caller):
|
||||
with open(self.file, 'wb') as configfile:
|
||||
self.p.write(configfile)
|
||||
|
||||
log.debug('Saved settings')
|
||||
self.on_save.send(self)
|
||||
|
||||
def addSection(self, section):
|
||||
if not self.p.has_section(section):
|
||||
self.p.add_section(section)
|
||||
|
||||
def setDefault(self, section, option, value):
|
||||
if not self.p.has_option(section, option):
|
||||
self.p.set(section, option, value)
|
||||
|
||||
def is_int(self, value):
|
||||
try:
|
||||
int(value)
|
||||
return True
|
||||
except ValueError:
|
||||
return False
|
||||
@@ -0,0 +1,64 @@
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy import orm
|
||||
|
||||
|
||||
class DatabaseError(Exception):
|
||||
"""Custom exceptions related to the database."""
|
||||
pass
|
||||
|
||||
|
||||
def _session_cls_cache(cache={}):
|
||||
"""Holds a dictionary to cache session objects."""
|
||||
return cache
|
||||
|
||||
|
||||
def get_session(engine=None, test=False):
|
||||
"""
|
||||
Get the current session or create a new one based on the engine.
|
||||
|
||||
>>> from couchpotato import db
|
||||
>>> from sqlalchemy import create_engine
|
||||
>>> engine = create_engine('sqlite:///:memory:')
|
||||
>>> session = db.get_session(engine)
|
||||
>>> session #doctest: +ELLIPSIS
|
||||
<sqlalchemy.orm.session.Session object at ...>
|
||||
|
||||
Once a session has been created, get_session will return session instances
|
||||
of the same Session class.
|
||||
>>> type(session) == type(db.get_session())
|
||||
True
|
||||
|
||||
If you create multiple sessions for different engines, you need to
|
||||
specify which session you want by passing the engine explicitely.
|
||||
|
||||
>>> other_engine = create_engine('sqlite:///:memory:')
|
||||
>>> other_session = db.get_session(other_engine)
|
||||
>>> type(other_session) is type(db.get_session(other_engine))
|
||||
True
|
||||
|
||||
"""
|
||||
cache = _session_cls_cache()
|
||||
|
||||
assert not(engine and test), "Cannot pass both test and engine."
|
||||
# It doesn't make sense to both pass an engine and instruct the function
|
||||
# to create a new engine. Decide what you want to do, but not both.
|
||||
if test:
|
||||
in_memory = sa.create_engine('sqlite:///:memory:')
|
||||
session = orm.sessionmaker(bind=in_memory)()
|
||||
# create Session class ^ ^
|
||||
# create Session instance ^
|
||||
elif engine:
|
||||
key = (engine, )
|
||||
if key not in cache:
|
||||
cache[key] = orm.sessionmaker(bind=engine)
|
||||
session = cache[key]()
|
||||
elif len(cache) == 1:
|
||||
session = (cache[key] for key in cache).next()()
|
||||
# return the first element ^ ^
|
||||
# instantiate session ^
|
||||
elif len(cache) >= 1:
|
||||
raise DatabaseError("Multiple Session classes found. Choose one.")
|
||||
else:
|
||||
raise DatabaseError("No session found. You need to create one.")
|
||||
|
||||
return session
|
||||
@@ -0,0 +1,64 @@
|
||||
from blinker import signal
|
||||
from couchpotato.core.logger import CPLog
|
||||
import glob
|
||||
import os
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
class SettingsLoader:
|
||||
|
||||
configs = {}
|
||||
|
||||
def __init__(self, root = ''):
|
||||
|
||||
self.settings_register = signal('settings.register')
|
||||
self.settings_save = signal('settings.save')
|
||||
|
||||
self.paths = {
|
||||
'plugins' : ('couchpotato.core.plugins', os.path.join(root, 'couchpotato', 'core', 'plugins')),
|
||||
'providers' : ('couchpotato.core.providers', os.path.join(root, 'couchpotato', 'core', 'providers')),
|
||||
}
|
||||
|
||||
for type, tuple in self.paths.iteritems():
|
||||
self.addFromDir(tuple[0], tuple[1])
|
||||
|
||||
def run(self):
|
||||
did_save = 0
|
||||
|
||||
for module, plugin_name in self.configs.iteritems():
|
||||
did_save += self.loadConfig(module, plugin_name, save = False)
|
||||
|
||||
if did_save:
|
||||
self.settings_save.send()
|
||||
|
||||
def addFromDir(self, module, dir):
|
||||
|
||||
for file in glob.glob(os.path.join(dir, '*')):
|
||||
name = os.path.basename(file)
|
||||
if os.path.isdir(os.path.join(dir, name)):
|
||||
self.addConfig(module, name)
|
||||
|
||||
def loadConfig(self, module, name, save = True):
|
||||
module_name = '%s.%s' % (module, name)
|
||||
try:
|
||||
m = getattr(self.loadModule(module_name), name)
|
||||
(section, options) = m.config
|
||||
self.settings_register.send(section, options = options, save = save)
|
||||
|
||||
return True
|
||||
except Exception, e:
|
||||
log.error("Failed loading config for %s: %s" % (name, e))
|
||||
return False
|
||||
|
||||
def addConfig(self, module, name):
|
||||
self.configs[module] = name
|
||||
|
||||
def loadModule(self, name):
|
||||
try:
|
||||
m = __import__(name)
|
||||
splitted = name.split('.')
|
||||
for sub in splitted[1:-1]:
|
||||
m = getattr(m, sub)
|
||||
return m
|
||||
except:
|
||||
raise
|
||||
@@ -0,0 +1,53 @@
|
||||
from elixir import *
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import scoped_session, sessionmaker
|
||||
from sqlalchemy.schema import ThreadLocalMetaData
|
||||
|
||||
# We would like to be able to create this schema in a specific database at
|
||||
# will, so we can test it easily.
|
||||
# Make elixir not bind to any session to make this possible.
|
||||
#
|
||||
# http://elixir.ematia.de/trac/wiki/Recipes/MultipleDatabasesOneMetadata
|
||||
__session__ = None
|
||||
|
||||
|
||||
class Resource(Entity):
|
||||
"""Represents a resource of movies. This recources can be online or
|
||||
offline."""
|
||||
name = Field(UnicodeString(255))
|
||||
path = Field(UnicodeString(255))
|
||||
releases = OneToMany('Release')
|
||||
|
||||
|
||||
class Release(Entity):
|
||||
"""Logically groups all files that belong to a certain release, such as
|
||||
parts of a movie, subtitles, nfo, trailers etc."""
|
||||
files = OneToMany('File')
|
||||
mooli_id = Field(Integer)
|
||||
resource = ManyToOne('Resource')
|
||||
|
||||
|
||||
class File(Entity):
|
||||
"""File that belongs to a release."""
|
||||
history = OneToMany('RenameHistory')
|
||||
path = Field(UnicodeString(255), nullable = False, unique = True)
|
||||
# Subtitles can have multiple parts, too
|
||||
part = Field(Integer)
|
||||
release = ManyToOne('Release')
|
||||
# Let's remember the size so we know about offline media.
|
||||
size = Field(Integer, nullable = False)
|
||||
type = ManyToOne('FileType')
|
||||
|
||||
|
||||
class FileType(Entity):
|
||||
"""Types could be trailer, subtitle, movie, partial movie etc."""
|
||||
identifier = Field(String(20), unique = True)
|
||||
name = Field(UnicodeString(255), nullable = False)
|
||||
files = OneToMany('File')
|
||||
|
||||
|
||||
class RenameHistory(Entity):
|
||||
"""Remembers from where to where files have been moved."""
|
||||
file = ManyToOne('File')
|
||||
old = Field(String(255))
|
||||
new = Field(String(255))
|
||||
Reference in new issue
Block a user