Added api and front_end as Modules

This commit is contained in:
Ruud committed 2011-02-13 01:58:56 +01:00
1 parent 09135e1738
commit 38a9ae2592
13 files changed
+76 -24

No files matched your search

+3
View File
@@ -1,3 +1,5 @@
from uuid import uuid4
config = ('global', {
'debug': False,
'host': '0.0.0.0',
@@ -6,4 +8,5 @@ config = ('global', {
'password': '',
'launch_browser': True,
'url_base': '',
'api_key': uuid4().hex,
})
+83
View File
@@ -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
+64
View File
@@ -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
+64
View File
@@ -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
+53
View File
@@ -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))