Restructuring
Logging Basic config loading from plugins/providers
This commit is contained in:
1 parent
8be7cba417
commit
722731c8bc
14 files changed
+229
-22
No files matched your search
@@ -0,0 +1,2 @@
|
|||||||
|
/settings.conf
|
||||||
|
/logs/*.log
|
||||||
+8
-9
@@ -1,16 +1,21 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
"""Wrapper for the command line interface."""
|
"""Wrapper for the command line interface."""
|
||||||
|
|
||||||
import os
|
|
||||||
from os.path import dirname, isfile
|
from os.path import dirname, isfile
|
||||||
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
|
# Root path
|
||||||
|
base_path = dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
|
# Insert local directories into path
|
||||||
|
sys.path.insert(0, os.path.join(base_path, 'libs'))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from couchpotato import cli
|
from couchpotato import cli
|
||||||
except ImportError:
|
except ImportError, e:
|
||||||
print "Checking local dependencies..."
|
print "Checking local dependencies..."
|
||||||
if isfile(__file__):
|
if isfile(__file__):
|
||||||
cwd = dirname(__file__)
|
cwd = dirname(__file__)
|
||||||
@@ -31,12 +36,6 @@ except ImportError:
|
|||||||
print "=" * 78
|
print "=" * 78
|
||||||
print stderr
|
print stderr
|
||||||
print "=" * 78
|
print "=" * 78
|
||||||
print "Registering libraries..."
|
|
||||||
# Insert local directories into path
|
|
||||||
lib_path = os.path.join(os.path.abspath(cwd), 'libs')
|
|
||||||
src_path = os.path.join(os.path.abspath(cwd), 'src')
|
|
||||||
sys.path.insert(0, lib_path)
|
|
||||||
sys.path.insert(0, src_path)
|
|
||||||
|
|
||||||
print "Passing execution to couchpotato..."
|
print "Passing execution to couchpotato..."
|
||||||
try:
|
try:
|
||||||
@@ -53,4 +52,4 @@ except ImportError:
|
|||||||
raise NotImplementedError("Don't know how to do that.")
|
raise NotImplementedError("Don't know how to do that.")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
cli.cmd_couchpotato()
|
cli.cmd_couchpotato(base_path)
|
||||||
+52
-6
@@ -1,8 +1,54 @@
|
|||||||
|
from blinker import signal
|
||||||
from couchpotato import app
|
from couchpotato import app
|
||||||
import argparse
|
from couchpotato.settings import Settings
|
||||||
|
from logging import handlers
|
||||||
|
from optparse import OptionParser
|
||||||
|
import logging
|
||||||
|
import os.path
|
||||||
|
import sys
|
||||||
|
|
||||||
def cmd_couchpotato():
|
|
||||||
"""Commandline entry point."""
|
def cmd_couchpotato(base_path):
|
||||||
# Make sure views are imported and registered.
|
'''Commandline entry point.'''
|
||||||
import couchpotato.views
|
|
||||||
app.run(debug=True)
|
# Options
|
||||||
|
parser = OptionParser('usage: %prog [options]')
|
||||||
|
parser.add_option('-l', '--logdir', dest = 'logdir', default = 'logs', help = 'log DIRECTORY (default ./logs)')
|
||||||
|
parser.add_option('-t', '--test', '--debug', action = 'store_true', dest = 'debug', help = 'Debug mode')
|
||||||
|
parser.add_option('-q', '--quiet', action = 'store_true', dest = 'quiet', help = "Don't log to console")
|
||||||
|
parser.add_option('-d', '--daemon', action = 'store_true', dest = 'daemon', help = 'Daemonize the app')
|
||||||
|
|
||||||
|
(options, args) = parser.parse_args(sys.argv[1:])
|
||||||
|
|
||||||
|
|
||||||
|
# Register settings
|
||||||
|
settings = Settings('settings.conf')
|
||||||
|
register = signal('settings_register')
|
||||||
|
register.connect(settings.registerDefaults)
|
||||||
|
|
||||||
|
debug = options.debug or settings.get('environment') == 'development'
|
||||||
|
|
||||||
|
# Logger
|
||||||
|
logger = logging.getLogger()
|
||||||
|
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s', '%H:%M:%S')
|
||||||
|
level = logging.DEBUG if debug else logging.INFO
|
||||||
|
logger.setLevel(level)
|
||||||
|
|
||||||
|
# Output logging information to screen
|
||||||
|
if not options.quiet:
|
||||||
|
hdlr = logging.StreamHandler(sys.stderr)
|
||||||
|
hdlr.setFormatter(formatter)
|
||||||
|
logger.addHandler(hdlr)
|
||||||
|
|
||||||
|
# Output logging information to file
|
||||||
|
hdlr2 = handlers.RotatingFileHandler(os.path.join(options.logdir, 'CouchPotato.log'), 'a', 5000000, 4)
|
||||||
|
hdlr2.setFormatter(formatter)
|
||||||
|
logger.addHandler(hdlr2)
|
||||||
|
|
||||||
|
|
||||||
|
# Load config
|
||||||
|
from couchpotato.settings.loader import SettingsLoader
|
||||||
|
SettingsLoader(root = base_path)
|
||||||
|
|
||||||
|
# Create app
|
||||||
|
app.run(host = settings.get('host'), port = int(settings.get('port')), debug = debug)
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
config = ('global', {
|
||||||
|
'environment': 'production',
|
||||||
|
'host': '0.0.0.0',
|
||||||
|
'port': 5000,
|
||||||
|
'username': '',
|
||||||
|
'password': '',
|
||||||
|
'launch_browser': True,
|
||||||
|
'url_base': '',
|
||||||
|
})
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
from couchpotato import app
|
||||||
|
|
||||||
|
class CPLog():
|
||||||
|
|
||||||
|
context = ''
|
||||||
|
|
||||||
|
def __init__(self, context = ''):
|
||||||
|
self.context = context
|
||||||
|
self.logger = app.logger
|
||||||
|
|
||||||
|
def info(self, msg):
|
||||||
|
self.logger.info(self.addContext(msg))
|
||||||
|
|
||||||
|
def debug(self, msg):
|
||||||
|
self.logger.debug(self.addContext(msg))
|
||||||
|
|
||||||
|
def error(self, msg):
|
||||||
|
self.logger.error(self.addContext(msg))
|
||||||
|
|
||||||
|
def addContext(self, msg):
|
||||||
|
return '[%+25.25s] %s' % (self.context[-25:], msg)
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
config = ('Renamer', {
|
||||||
|
'enabled': False,
|
||||||
|
'cleanup': False
|
||||||
|
})
|
||||||
Whitespace-only changes.
@@ -0,0 +1,3 @@
|
|||||||
|
config = ('TheMovieDB', {
|
||||||
|
'key': '9b939aee0aaafc12a65bf448e4af9543'
|
||||||
|
})
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
from __future__ import with_statement
|
||||||
|
from blinker import signal, Signal
|
||||||
|
from couchpotato.core.logger import CPLog
|
||||||
|
import ConfigParser
|
||||||
|
import time
|
||||||
|
|
||||||
|
log = CPLog(__name__)
|
||||||
|
settings = signal('settings_register')
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
def parser(self):
|
||||||
|
return self.p
|
||||||
|
|
||||||
|
def sections(self):
|
||||||
|
return self.s
|
||||||
|
|
||||||
|
def registerDefaults(self, section_name, options):
|
||||||
|
|
||||||
|
self.addSection(section_name)
|
||||||
|
for option, value in options.iteritems():
|
||||||
|
self.setDefault(section_name, option, value)
|
||||||
|
|
||||||
|
log.debug('Registered defaults %s: %s' % (section_name, options))
|
||||||
|
self.on_register.send(self)
|
||||||
|
|
||||||
|
self.save()
|
||||||
|
|
||||||
|
def set(self, section, option, value):
|
||||||
|
return self.p.set(section, option, value)
|
||||||
|
|
||||||
|
def get(self, option = '', section = 'global'):
|
||||||
|
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()
|
||||||
|
|
||||||
|
def is_int(self, value):
|
||||||
|
try:
|
||||||
|
int(value)
|
||||||
|
return True
|
||||||
|
except ValueError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
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)
|
||||||
File renamed without changes.
@@ -0,0 +1,47 @@
|
|||||||
|
from blinker import signal
|
||||||
|
from couchpotato.core.logger import CPLog
|
||||||
|
import glob
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
log = CPLog(__name__)
|
||||||
|
|
||||||
|
class SettingsLoader:
|
||||||
|
|
||||||
|
def __init__(self, root = ''):
|
||||||
|
|
||||||
|
self.register = signal('settings_register')
|
||||||
|
|
||||||
|
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.loadFromDir(tuple[0], tuple[1])
|
||||||
|
|
||||||
|
def loadFromDir(self, module, dir):
|
||||||
|
for file in glob.glob(os.path.join(dir, '*')):
|
||||||
|
plugin_name = os.path.basename(file)
|
||||||
|
plugin_dir = os.path.join(dir, plugin_name)
|
||||||
|
if os.path.isdir(plugin_dir):
|
||||||
|
self.loadConfig(module, plugin_name)
|
||||||
|
|
||||||
|
def loadConfig(self, module, name):
|
||||||
|
module_name = '%s.%s' % (module, name)
|
||||||
|
try:
|
||||||
|
m = getattr(self.loadModule(module_name), name)
|
||||||
|
(section, options) = m.config
|
||||||
|
self.register.send(section, options = options)
|
||||||
|
except:
|
||||||
|
log.error("Failed loading config for %s" % 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
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
from sqlalchemy.orm import scoped_session, sessionmaker
|
|
||||||
from sqlalchemy import create_engine
|
|
||||||
from sqlalchemy.schema import ThreadLocalMetaData
|
|
||||||
from elixir import *
|
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
|
# We would like to be able to create this schema in a specific database at
|
||||||
# will, so we can test it easily.
|
# will, so we can test it easily.
|
||||||
@@ -30,19 +30,19 @@ class Release(Entity):
|
|||||||
class File(Entity):
|
class File(Entity):
|
||||||
"""File that belongs to a release."""
|
"""File that belongs to a release."""
|
||||||
history = OneToMany('RenameHistory')
|
history = OneToMany('RenameHistory')
|
||||||
path = Field(UnicodeString(255), nullable=False, unique=True)
|
path = Field(UnicodeString(255), nullable = False, unique = True)
|
||||||
# Subtitles can have multiple parts, too
|
# Subtitles can have multiple parts, too
|
||||||
part = Field(Integer)
|
part = Field(Integer)
|
||||||
release = ManyToOne('Release')
|
release = ManyToOne('Release')
|
||||||
# Let's remember the size so we know about offline media.
|
# Let's remember the size so we know about offline media.
|
||||||
size = Field(Integer, nullable=False)
|
size = Field(Integer, nullable = False)
|
||||||
type = ManyToOne('FileType')
|
type = ManyToOne('FileType')
|
||||||
|
|
||||||
|
|
||||||
class FileType(Entity):
|
class FileType(Entity):
|
||||||
"""Types could be trailer, subtitle, movie, partial movie etc."""
|
"""Types could be trailer, subtitle, movie, partial movie etc."""
|
||||||
identifier = Field(String(20), unique=True)
|
identifier = Field(String(20), unique = True)
|
||||||
name = Field(UnicodeString(255), nullable=False)
|
name = Field(UnicodeString(255), nullable = False)
|
||||||
files = OneToMany('File')
|
files = OneToMany('File')
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
Reference in new issue
Block a user