Browse Source

environment class

get_session
pull/1/merge
Ruud 14 years ago
parent
commit
cdde98653e
  1. 23
      couchpotato/__init__.py
  2. 10
      couchpotato/api/__init__.py
  3. 33
      couchpotato/cli.py
  4. 6
      couchpotato/core/auth.py
  5. 2
      couchpotato/core/settings/__init__.py
  6. 64
      couchpotato/core/settings/db.py
  7. 24
      couchpotato/core/settings/model.py
  8. 24
      couchpotato/environment.py

23
couchpotato/__init__.py

@ -1,10 +1,14 @@
from couchpotato.core.auth import requires_auth
from couchpotato.core.logger import CPLog
from couchpotato.environment import Env
from flask.app import Flask
from flask.globals import request
from flask.helpers import url_for
from flask.module import Module
from flask.templating import render_template
from sqlalchemy.engine import create_engine
from sqlalchemy.orm import scoped_session
from sqlalchemy.orm.session import sessionmaker
from werkzeug.utils import redirect
import os
@ -12,6 +16,12 @@ app = Flask(__name__)
log = CPLog(__name__)
web = Module(__name__, 'web')
def get_session(engine):
engine = engine if engine else get_engine()
return scoped_session(sessionmaker(autoflush = True, transactional = True, bind = engine))
def get_engine():
return create_engine('sqlite:///' + Env.get('db_path'), echo = Env.get('debug'))
@web.route('/')
@requires_auth
@ -23,16 +33,3 @@ def page_not_found(error):
index_url = url_for('web.index')
url = request.path[len(index_url):]
return redirect(index_url + '#' + url)
@web.route('/exit')
@requires_auth
def exit():
# stopping code
pass
@web.route('/restart')
@requires_auth
def restart():
# restart code
pass

10
couchpotato/api/__init__.py

@ -1,6 +1,7 @@
from couchpotato.api.file_browser import FileBrowser
from couchpotato.core.settings import settings
from couchpotato.core.settings.loader import settings_loader
from couchpotato.core.settings.model import Resource
from couchpotato.environment import Env
from flask import Module
from flask.helpers import jsonify
import flask
@ -16,7 +17,7 @@ def index():
def settings_view():
return jsonify({
'sections': settings_loader.sections,
'values': settings.getValues()
'values': Env.get('settings').getValues()
})
@api.route('setting.save/')
@ -27,8 +28,8 @@ def setting_save_view():
option = a.get('name')
value = a.get('value')
settings.set(section, option, value)
settings.save()
Env.get('settings').set(section, option, value)
Env.get('settings').save()
return jsonify({
'success': True,
@ -36,6 +37,7 @@ def setting_save_view():
@api.route('movie/')
def movie():
return jsonify({
'success': True,
'movies': [

33
couchpotato/cli.py

@ -1,6 +1,8 @@
from argparse import ArgumentParser
from couchpotato import web
from couchpotato import get_engine, web
from couchpotato.api import api
from couchpotato.core.settings.model import *
from couchpotato.environment import Env
from libs.daemon import createDaemon
from logging import handlers
import logging
@ -13,8 +15,8 @@ def cmd_couchpotato(base_path, args):
# Options
parser = ArgumentParser()
parser.add_argument('-s', '--datadir', default = base_path,
dest = 'data_dir', help = 'Absolute or ~/ path, where settings/logs/database data is saved (default ./)')
parser.add_argument('-s', '--datadir', default = os.path.join(base_path, '_data'),
dest = 'data_dir', help = 'Absolute or ~/ path, where settings/logs/database data is saved (default ./_data)')
parser.add_argument('-t', '--test', '--debug', action = 'store_true',
dest = 'debug', help = 'Debug mode')
parser.add_argument('-q', '--quiet', action = 'store_true',
@ -41,12 +43,15 @@ def cmd_couchpotato(base_path, args):
createDaemon()
# Register settings
from couchpotato.core.settings import settings
settings.setFile(os.path.join(options.data_dir, 'settings.conf'))
# Register environment settings
Env.get('settings').setFile(os.path.join(options.data_dir, 'settings.conf'))
Env.set('app_dir', base_path)
Env.set('data_dir', options.data_dir)
Env.set('db_path', os.path.join(options.data_dir, 'couchpotato.db'))
# Determine debug
debug = options.debug or settings.get('debug', default = False)
debug = options.debug or Env.get('settings').get('debug', default = False)
Env.set('debug', debug)
# Logger
@ -83,15 +88,21 @@ def cmd_couchpotato(base_path, args):
settings_loader.run()
# Configure Database
from elixir import setup_all, create_all
setup_all()
create_all(get_engine())
# Create app
from couchpotato import app
api_key = settings.get('api_key')
url_base = '/' + settings.get('url_base') if settings.get('url_base') else ''
api_key = Env.get('settings').get('api_key')
url_base = '/' + Env.get('settings').get('url_base') if Env.get('settings').get('url_base') else ''
reloader = debug and not options.daemonize
# Basic config
app.host = settings.get('host', default = '0.0.0.0')
app.port = settings.get('port', default = 5000)
app.host = Env.get('settings').get('host', default = '0.0.0.0')
app.port = Env.get('settings').get('port', default = 5000)
app.debug = debug
app.secret_key = api_key
app.static_path = url_base + '/static'

6
couchpotato/core/auth.py

@ -1,9 +1,9 @@
from couchpotato.core.settings import settings
from couchpotato.environment import Env
from flask import request, Response
from functools import wraps
def check_auth(username, password):
return username == settings.get('username') and password == settings.get('password')
return username == Env.get('settings').get('username') and password == Env.get('settings').get('password')
def authenticate():
return Response(
@ -16,7 +16,7 @@ def requires_auth(f):
@wraps(f)
def decorated(*args, **kwargs):
auth = request.authorization
if settings.get('username') and (not auth or not check_auth(auth.username, auth.password)):
if Env.get('settings').get('username') and (not auth or not check_auth(auth.username, auth.password)):
return authenticate()
return f(*args, **kwargs)

2
couchpotato/core/settings/__init__.py

@ -94,5 +94,3 @@ class Settings():
return True
except ValueError:
return False
settings = Settings()

64
couchpotato/core/settings/db.py

@ -1,64 +0,0 @@
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

24
couchpotato/core/settings/model.py

@ -1,7 +1,10 @@
from elixir import *
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.schema import ThreadLocalMetaData
from elixir.entity import Entity
from elixir.fields import Field
from elixir.options import options_defaults
from elixir.relationships import OneToMany, ManyToOne
from sqlalchemy.types import Integer, String, Unicode
options_defaults["shortnames"] = True
# We would like to be able to create this schema in a specific database at
# will, so we can test it easily.
@ -10,12 +13,11 @@ from sqlalchemy.schema import ThreadLocalMetaData
# 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))
"""Represents a resource of movies.
This resources can be online or offline."""
name = Field(Unicode(255))
path = Field(Unicode(255))
releases = OneToMany('Release')
@ -30,7 +32,7 @@ class Release(Entity):
class File(Entity):
"""File that belongs to a release."""
history = OneToMany('RenameHistory')
path = Field(UnicodeString(255), nullable = False, unique = True)
path = Field(Unicode(255), nullable = False, unique = True)
# Subtitles can have multiple parts, too
part = Field(Integer)
release = ManyToOne('Release')
@ -42,7 +44,7 @@ class File(Entity):
class FileType(Entity):
"""Types could be trailer, subtitle, movie, partial movie etc."""
identifier = Field(String(20), unique = True)
name = Field(UnicodeString(255), nullable = False)
name = Field(Unicode(255), nullable = False)
files = OneToMany('File')

24
couchpotato/environment.py

@ -0,0 +1,24 @@
from couchpotato.core.settings import Settings
class Env:
_debug = False
_settings = Settings()
_options = None
_args = None
_quiet = False
_app_dir = ""
_data_dir = ""
_db_path = ""
@staticmethod
def doDebug():
return Env._debug
@staticmethod
def get(attr):
return getattr(Env, '_' + attr)
@staticmethod
def set(attr, value):
return setattr(Env, '_' + attr, value)
Loading…
Cancel
Save