1
0
mirror of https://github.com/spl0k/supysonic.git synced 2024-12-22 08:56:17 +00:00

Improve config.py to read file only in check

This commit is contained in:
Óscar García Amor 2017-08-08 10:37:22 +02:00
parent 09ce5ae455
commit a1619dd96a
10 changed files with 153 additions and 93 deletions

70
.gitignore vendored
View File

@ -1,6 +1,68 @@
*.pyc
.*.sw[a-z]
*~
# ---> Python
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
MANIFEST
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
# Translations
*.mo
*.pot
# Django stuff:
*.log
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# ---> Vim
[._]*.s[a-w][a-z]
[._]s[a-w][a-z]
*.un~
Session.vim
.netrwhist
*~

View File

@ -20,7 +20,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys, cmd, argparse, getpass, time
from supysonic.config import Config
from supysonic import config
from supysonic.db import get_store, Folder, User
from supysonic.managers.folder import FolderManager
@ -225,10 +225,10 @@ class CLI(cmd.Cmd):
print "Successfully changed '{}' password".format(name)
if __name__ == "__main__":
if not Config().check():
if not config.check():
sys.exit(1)
cli = CLI(get_store(Config().get('base', 'database_uri')))
cli = CLI(get_store(config.get('base', 'database_uri')))
if len(sys.argv) > 1:
cli.onecmd(' '.join(sys.argv[1:]))
else:

View File

@ -27,7 +27,7 @@ import codecs
from xml.etree import ElementTree
from supysonic import scanner
from supysonic.config import Config
from supysonic import config
from supysonic.web import app, store
from supysonic.db import Track, Album, Artist, Folder, User, ClientPrefs, now
from . import get_entity
@ -71,14 +71,14 @@ def stream_media():
if format and format != 'raw' and format != src_suffix:
dst_suffix = format
dst_mimetype = Config().get_mime(dst_suffix)
dst_mimetype = config.get_mime(dst_suffix)
if format != 'raw' and (dst_suffix != src_suffix or dst_bitrate != res.bitrate):
transcoder = Config().get('transcoding', 'transcoder_{}_{}'.format(src_suffix, dst_suffix))
decoder = Config().get('transcoding', 'decoder_' + src_suffix) or Config().get('transcoding', 'decoder')
encoder = Config().get('transcoding', 'encoder_' + dst_suffix) or Config().get('transcoding', 'encoder')
transcoder = config.get('transcoding', 'transcoder_{}_{}'.format(src_suffix, dst_suffix))
decoder = config.get('transcoding', 'decoder_' + src_suffix) or config.get('transcoding', 'decoder')
encoder = config.get('transcoding', 'encoder_' + dst_suffix) or config.get('transcoding', 'encoder')
if not transcoder and (not decoder or not encoder):
transcoder = Config().get('transcoding', 'transcoder')
transcoder = config.get('transcoding', 'transcoder')
if not transcoder:
message = 'No way to transcode from {} to {}'.format(src_suffix, dst_suffix)
app.logger.info(message)
@ -154,7 +154,7 @@ def cover_art():
if size > im.size[0] and size > im.size[1]:
return send_file(os.path.join(res.path, 'cover.jpg'))
size_path = os.path.join(Config().get('webapp', 'cache_dir'), str(size))
size_path = os.path.join(config.get('webapp', 'cache_dir'), str(size))
path = os.path.join(size_path, str(res.id))
if os.path.exists(path):
return send_file(path)

View File

@ -15,59 +15,57 @@ import mimetypes
import os
import tempfile
class Config(object):
# Seek for standard locations
config_file = [
'supysonic.conf',
os.path.expanduser('~/.config/supysonic/supysonic.conf'),
os.path.expanduser('~/.supysonic'),
'/etc/supysonic'
]
config = ConfigParser({ 'cache_dir': os.path.join(tempfile.gettempdir(), 'supysonic') })
def check():
"""
Config object to work with config file
Checks the config file and mandatory fields
"""
def __init__(self):
# Seek for standard locations
config_file = [
'supysonic.conf',
os.path.expanduser('~/.config/supysonic/supysonic.conf'),
os.path.expanduser('~/.supysonic'),
'/etc/supysonic'
]
self.config = ConfigParser({ 'cache_dir': os.path.join(tempfile.gettempdir(), 'supysonic') })
# Try read config file or raise error
try:
self.config.read(config_file)
except Exception as e:
err = 'Config file is corrupted.\n{0}'.format(e)
raise SystemExit(err)
try:
config.read(config_file)
except Exception as e:
err = 'Config file is corrupted.\n{0}'.format(e)
raise SystemExit(err)
def check(self):
"""
Checks the config for mandatory fields
"""
try:
self.config.get('base', 'database_uri')
except (NoSectionError, NoOptionError):
raise SystemExit('No database URI set')
return True
try:
config.get('base', 'database_uri')
except (NoSectionError, NoOptionError):
raise SystemExit('No database URI set')
def get(self, section, option):
"""
Returns a config option value from config file
return True
:param section: section where the option is stored
:param option: option name
:return: a config option value
:rtype: string
"""
try:
return self.config.get(section, option)
except (NoSectionError, NoOptionError):
return None
def get(section, option):
"""
Returns a config option value from config file
def get_mime(self, extension):
"""
Returns mimetype of an extension based on config file
:param section: section where the option is stored
:param option: option name
:return: a config option value
:rtype: string
"""
try:
return config.get(section, option)
except (NoSectionError, NoOptionError):
return None
:param extension: extension string
:return: mimetype
:rtype: string
"""
guessed_mime = mimetypes.guess_type('dummy.' + extension, False)[0]
config_mime = self.get('mimetypes', extension)
default_mime = 'application/octet-stream'
return guessed_mime or config_mime or default_mime
def get_mime(extension):
"""
Returns mimetype of an extension based on config file
:param extension: extension string
:return: mimetype
:rtype: string
"""
guessed_mime = mimetypes.guess_type('dummy.' + extension, False)[0]
config_mime = get('mimetypes', extension)
default_mime = 'application/octet-stream'
return guessed_mime or config_mime or default_mime

View File

@ -27,7 +27,7 @@ from storm.variables import Variable
import uuid, datetime, time
import os.path
from supysonic.config import Config
from supysonic import config
def now():
return datetime.datetime.now().replace(microsecond = 0)
@ -213,7 +213,7 @@ class Track(object):
if prefs and prefs.format and prefs.format != self.suffix():
info['transcodedSuffix'] = prefs.format
info['transcodedContentType'] = Config().get_mime(prefs.format)
info['transcodedContentType'] = config.get_mime(prefs.format)
return info

View File

@ -24,7 +24,7 @@ from supysonic.web import app, store
from supysonic.managers.user import UserManager
from supysonic.db import User, ClientPrefs
import uuid, csv
from supysonic.config import Config
from supysonic import config
from supysonic.lastfm import LastFm
@app.before_request
@ -43,12 +43,12 @@ def user_index():
def user_profile(uid):
if uid == 'me':
prefs = store.find(ClientPrefs, ClientPrefs.user_id == uuid.UUID(session.get('userid')))
return render_template('profile.html', user = UserManager.get(store, session.get('userid'))[1], api_key = Config().get('lastfm', 'api_key'), clients = prefs, admin = UserManager.get(store, session.get('userid'))[1].admin)
return render_template('profile.html', user = UserManager.get(store, session.get('userid'))[1], api_key = config.get('lastfm', 'api_key'), clients = prefs, admin = UserManager.get(store, session.get('userid'))[1].admin)
else:
if not UserManager.get(store, session.get('userid'))[1].admin or not UserManager.get(store, uid)[0] is UserManager.SUCCESS:
return redirect(url_for('index'))
prefs = store.find(ClientPrefs, ClientPrefs.user_id == uuid.UUID(uid))
return render_template('profile.html', user = UserManager.get(store, uid)[1], api_key = Config().get('lastfm', 'api_key'), clients = prefs, admin = UserManager.get(store, session.get('userid'))[1].admin)
return render_template('profile.html', user = UserManager.get(store, uid)[1], api_key = config.get('lastfm', 'api_key'), clients = prefs, admin = UserManager.get(store, session.get('userid'))[1].admin)
@app.route('/user/<uid>', methods = [ 'POST' ])
def update_clients(uid):

View File

@ -19,13 +19,13 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import requests, hashlib
from supysonic.config import Config
from supysonic import config
class LastFm:
def __init__(self, user, logger):
self.__user = user
self.__api_key = Config().get('lastfm', 'api_key')
self.__api_secret = Config().get('lastfm', 'secret')
self.__api_key = config.get('lastfm', 'api_key')
self.__api_secret = config.get('lastfm', 'secret')
self.__enabled = self.__api_key is not None and self.__api_secret is not None
self.__logger = logger

View File

@ -25,7 +25,7 @@ import mutagen
from storm.expr import ComparableExpr, compile, Like
from storm.exceptions import NotSupportedError
from supysonic.config import Config
from supysonic import config
from supysonic.db import Folder, Artist, Album, Track, User, PlaylistTrack
from supysonic.db import StarredFolder, StarredArtist, StarredAlbum, StarredTrack
from supysonic.db import RatingFolder, RatingTrack
@ -63,7 +63,7 @@ class Scanner:
self.__deleted_albums = 0
self.__deleted_tracks = 0
extensions = Config().get('base', 'scanner_extensions')
extensions = config.get('base', 'scanner_extensions')
self.__extensions = map(str.lower, extensions.split()) if extensions else None
self.__folders_to_check = set()
@ -166,7 +166,7 @@ class Scanner:
tr.duration = int(tag.info.length)
tr.bitrate = (tag.info.bitrate if hasattr(tag.info, 'bitrate') else int(os.path.getsize(path) * 8 / tag.info.length)) / 1000
tr.content_type = Config().get_mime(os.path.splitext(path)[1][1:])
tr.content_type = config.get_mime(os.path.splitext(path)[1][1:])
tr.last_modification = os.path.getmtime(path)
tralbum = self.__find_album(albumartist, album)

View File

@ -27,7 +27,7 @@ from watchdog.observers import Observer
from watchdog.events import PatternMatchingEventHandler
from supysonic import db
from supysonic.config import Config
from supysonic import config
from supysonic.scanner import Scanner
OP_SCAN = 1
@ -36,7 +36,7 @@ OP_MOVE = 4
class SupysonicWatcherEventHandler(PatternMatchingEventHandler):
def __init__(self, queue, logger):
extensions = Config().get('base', 'scanner_extensions')
extensions = config.get('base', 'scanner_extensions')
patterns = map(lambda e: "*." + e.lower(), extensions.split()) if extensions else None
super(SupysonicWatcherEventHandler, self).__init__(patterns = patterns, ignore_directories = True)
@ -133,7 +133,7 @@ class ScannerProcessingQueue(Thread):
continue
self.__logger.debug("Instantiating scanner")
store = db.get_store(Config().get('base', 'database_uri'))
store = db.get_store(config.get('base', 'database_uri'))
scanner = Scanner(store)
item = self.__next_item()
@ -201,17 +201,17 @@ class ScannerProcessingQueue(Thread):
class SupysonicWatcher(object):
def run(self):
if not Config().check():
if not config.check():
return
logger = logging.getLogger(__name__)
if Config().get('daemon', 'log_file'):
log_handler = TimedRotatingFileHandler(Config().get('daemon', 'log_file'), when = 'midnight')
if config.get('daemon', 'log_file'):
log_handler = TimedRotatingFileHandler(config.get('daemon', 'log_file'), when = 'midnight')
else:
log_handler = logging.NullHandler()
log_handler.setFormatter(logging.Formatter("%(asctime)s [%(levelname)s] %(message)s"))
logger.addHandler(log_handler)
if Config().get('daemon', 'log_level'):
if config.get('daemon', 'log_level'):
mapping = {
'DEBUG': logging.DEBUG,
'INFO': logging.INFO,
@ -219,9 +219,9 @@ class SupysonicWatcher(object):
'ERROR': logging.ERROR,
'CRTICAL': logging.CRITICAL
}
logger.setLevel(mapping.get(Config().get('daemon', 'log_level').upper(), logging.NOTSET))
logger.setLevel(mapping.get(config.get('daemon', 'log_level').upper(), logging.NOTSET))
store = db.get_store(Config().get('base', 'database_uri'))
store = db.get_store(config.get('base', 'database_uri'))
folders = store.find(db.Folder, db.Folder.root == True)
if not folders.count():

View File

@ -13,13 +13,13 @@ from flask import Flask, g
from os import makedirs, path
from werkzeug.local import LocalProxy
from supysonic.config import Config
from supysonic import config
from supysonic.db import get_store
# Supysonic database open
def get_db():
if not hasattr(g, 'database'):
g.database = get_store(Config().get('base', 'database_uri'))
g.database = get_store(config.get('base', 'database_uri'))
return g.database
# Supysonic database close
@ -33,17 +33,17 @@ def create_application():
global app
# Check config for mandatory fields
Config().check()
config.check()
# Test for the cache directory
if not path.exists(Config().get('webapp', 'cache_dir')):
os.makedirs(Config().get('webapp', 'cache_dir'))
if not path.exists(config.get('webapp', 'cache_dir')):
os.makedirs(config.get('webapp', 'cache_dir'))
# Flask!
app = Flask(__name__)
# Set a secret key for sessions
secret_key = Config().get('base', 'secret_key')
secret_key = config.get('base', 'secret_key')
# If secret key is not defined in config, set develop key
if secret_key is None:
app.secret_key = 'd3v3l0p'
@ -54,11 +54,11 @@ def create_application():
app.teardown_appcontext(close_db)
# Set loglevel
if Config().get('webapp', 'log_file'):
if config.get('webapp', 'log_file'):
import logging
from logging.handlers import TimedRotatingFileHandler
handler = TimedRotatingFileHandler(Config().get('webapp', 'log_file'), when = 'midnight')
if Config().get('webapp', 'log_level'):
handler = TimedRotatingFileHandler(config.get('webapp', 'log_file'), when = 'midnight')
if config.get('webapp', 'log_level'):
mapping = {
'DEBUG': logging.DEBUG,
'INFO': logging.INFO,
@ -66,7 +66,7 @@ def create_application():
'ERROR': logging.ERROR,
'CRTICAL': logging.CRITICAL
}
handler.setLevel(mapping.get(Config().get('webapp', 'log_level').upper(), logging.NOTSET))
handler.setLevel(mapping.get(config.get('webapp', 'log_level').upper(), logging.NOTSET))
app.logger.addHandler(handler)
# Import app sections