Browse Source

Merge a4e467f20e into 711310d0c3

pull/6468/merge
Ricky Grassmuck 8 years ago
committed by GitHub
parent
commit
bcd22e65c4
  1. 2
      CouchPotato.py
  2. 9
      config.ini
  3. 11
      couchpotato/runner.py
  4. 25
      init/runtime-config.ini
  5. 209
      libs/argparse_config.py

2
CouchPotato.py

@ -33,7 +33,7 @@ class Loader(object):
# Get options via arg
from couchpotato.runner import getOptions
self.options = getOptions(sys.argv[1:])
self.options = getOptions(sys.argv[1:], base_path)
# Load settings
settings = Env.get('settings')

9
config.ini

@ -0,0 +1,9 @@
# Runtime configuration file
# For all available options copy thefile located at
# "<Application-Home>/init/runtime-config.ini" to
# "<Application-Home>/config.ini"
# and edit it to fit your needs.
[default]
daemon:

11
couchpotato/runner.py

@ -13,6 +13,7 @@ import shutil
from CodernityDB.database_super_thread_safe import SuperThreadSafeDatabase
from argparse import ArgumentParser
import argparse_config
from cache import FileSystemCache
from couchpotato import KeyHandler, LoginHandler, LogoutHandler
from couchpotato.api import NonBlockHandler, ApiHandler
@ -27,9 +28,9 @@ from couchpotato.core.softchroot import SoftChrootInitError
try: from tornado.netutil import bind_unix_socket
except: pass
def getOptions(args):
def getOptions(args, base_path):
# Options
conf = os.path.join(base_path, "config.ini")
parser = ArgumentParser(prog = 'CouchPotato.py')
parser.add_argument('--data_dir',
dest = 'data_dir', help = 'Absolute or ~/ path of the data dir')
@ -45,7 +46,11 @@ def getOptions(args):
dest = 'daemon', help = 'Daemonize the app')
parser.add_argument('--pid_file',
dest = 'pid_file', help = 'Path to pidfile needed for daemon')
# parse applicaions runtime configuration file and set options
if os.path.exists(conf):
argparse_config.read_config_file(parser, conf)
options = parser.parse_args(args)
data_dir = os.path.expanduser(options.data_dir if options.data_dir else getDataDir())

25
init/runtime-config.ini

@ -0,0 +1,25 @@
# A template for the CouchPotatoServer config.ini file
# Do not change the [default] section heading
[default]
# Uncomment to run CouchPotato as a daemon
# daemon:
# Uncomment to specify CouchPotato's data directory
# data_dir: /apps/configs/couchpotato
# Uncomment to specify the location of CouchPotato's settings file
# config_file: /home/couchpotato/settings.conf
# Uncomment to specifiy the location of the PID file
# pid_file: /home/couchpotato/cp.pid
# Uncomment to run CP in debug mode
# debug:
# Uncomment to log messages to the console instead of the log files
# console_log:
# Uncomment to limit logging
# quiet:

209
libs/argparse_config.py

@ -0,0 +1,209 @@
"""
Author: tikitu
"""
import ConfigParser
from argparse import _SubParsersAction, _StoreAction, _StoreConstAction
import argparse
__version__ = '0.5.1'
def get_config_parser(filename):
config_parser = ConfigParser.SafeConfigParser(allow_no_value=True)
config_parser.read([filename])
return config_parser
def read_config_file(arg_parser, filename):
config_parser = get_config_parser(filename)
read_config_parser(arg_parser, config_parser)
def read_config_parser(arg_parser, config_parser):
ReadConfig(config_parser=config_parser).walk_parser(arg_parser)
def add_config_block_subcommand(arg_parser, subparsers,
config_parser=None,
only_non_defaults=False):
"""
Add a subcommand "config-block" to the arg_parser, to be used as follows:
In myprog.py:
subparsers = arg_parser.add_subparsers(..., dest='command')
add_config_block_subcommand(arg_parser, subparsers)
# ...
parsed_args = arg_parser.parse_args()
if parsed_args.command == 'config':
print parsed_args.func(parsed_args)
exit(0)
On the commandline:
$ myprog.py config default --username tikitu --secret xyzzy
[default]
username: tikitu
secret: xyzzy
:param arg_parser:
:param config_parser:
:param dest:
:param only_non_defaults:
:return: None
"""
config_command_parser = subparsers.add_parser('config')
config_command_parser.add_argument('block')
config_command_parser.add_argument('commandline', nargs=argparse.REMAINDER)
def handle_args(orig_parsed_args):
if config_parser is not None:
read_config_parser(arg_parser, config_parser)
args_for_commandline = list(orig_parsed_args.commandline)
if orig_parsed_args.block == 'default':
subparsers.add_parser('dummy-command')
args_for_commandline.append('dummy-command')
else:
args_for_commandline.insert(0, orig_parsed_args.block)
parsed_args = arg_parser.parse_args(args_for_commandline)
return generate_config(arg_parser, parsed_args,
section=orig_parsed_args.block,
only_non_defaults=only_non_defaults)
config_command_parser.set_defaults(func=handle_args)
def generate_config(arg_parser, parsed_args, section='default',
only_non_defaults=False):
action = GenerateConfig(parsed_args, section,
only_non_defaults=only_non_defaults)
action.walk_parser(arg_parser)
return action.contents
class ArgParserWalker(object):
def start_section(self, section_name):
raise NotImplementedError()
def end_section(self):
raise NotImplementedError()
def process_parser_action(self, action, is_store_const=False):
raise NotImplementedError()
def walk_parser(self, arg_parser):
try:
self.start_section('default')
for action in arg_parser._actions:
if isinstance(action, _StoreAction):
self.process_parser_action(action)
elif isinstance(action, _StoreConstAction):
self.process_parser_action(action, is_store_const=True)
elif isinstance(action, _SubParsersAction):
for command, sub_parser in action.choices.items():
self.start_section(command)
for sub_action in sub_parser._actions:
self.process_parser_action(sub_action)
self.end_section()
self.end_section()
except DefaultError as e:
arg_parser.error(
u'[{section_name}] config option "{option_string}" '
u'must be {type_transformer}() value, got: {value}'.format(
section_name=e.section_name,
option_string=e.option_string,
type_transformer=e.type_transformer.__name__,
value=e.value
))
class GenerateConfig(ArgParserWalker):
def __init__(self, parsed_args, section, only_non_defaults=False):
self.parsed_args = parsed_args
self._contents = []
self._only_non_defaults = only_non_defaults
self._section = section
self._in_sections = []
def start_section(self, section_name):
self._in_sections.append(section_name)
if section_name == self._section:
if self._contents:
self._contents.append(u'')
self._contents.append(u'[{0}]'.format(section_name))
def end_section(self):
self._in_sections.pop()
@property
def contents(self):
return u'\n'.join(self._contents + [u''])
def process_parser_action(self, action, is_store_const=False):
if self._in_sections[-1] != self._section:
return
# take the longest string, likely the most informative
action_name = list(action.option_strings)
action_name.sort(key=lambda s: len(s), reverse=True)
action_name = _convert_option_string(action_name[0])
action_value = getattr(self.parsed_args, action.dest, None)
if self._only_non_defaults and action_value == action.default:
action_value = None
if action_value is not None:
if is_store_const:
self._contents.append(action_name)
else:
self._contents.append(u'{action_name}: {default_value}'.format(
action_name=action_name,
default_value=action_value, # hope it prints as wanted...
))
class ReadConfig(ArgParserWalker):
def __init__(self, config_parser=None):
self.sections = []
self.config_parser = config_parser
def start_section(self, section_name):
self.sections.append(section_name)
def end_section(self):
self.sections.pop()
@property
def current_section(self):
return self.sections[-1] if self.sections else None
def process_parser_action(self, action, is_store_const=False):
for option_string in action.option_strings:
option_string = _convert_option_string(option_string)
if self.config_parser.has_option(self.current_section,
option_string):
if is_store_const:
action.default = action.const
else:
value = self.config_parser.get(self.current_section,
option_string)
type_transformer = (action.type if action.type is not None
else lambda x: x)
try:
action.default = type_transformer(value)
except:
raise DefaultError(self.current_section,
option_string,
value,
type_transformer)
action.required = False
class DefaultError(Exception):
def __init__(self, section_name, option_string, value, type_transformer):
self.section_name = section_name
self.option_string = option_string
self.value = value
self.type_transformer = type_transformer
def _convert_option_string(op_s):
return op_s.lstrip('-').replace('-', '_')
Loading…
Cancel
Save