Encapsulate config constants in Config class
This commit is contained in:
@@ -8,7 +8,7 @@ from tempfile import mkdtemp, NamedTemporaryFile
|
||||
import pytest
|
||||
|
||||
from tuir.theme import Theme
|
||||
from tuir.config import DEFAULT_THEMES
|
||||
from tuir.config import Config
|
||||
from tuir.exceptions import ConfigError
|
||||
|
||||
try:
|
||||
@@ -115,7 +115,7 @@ def test_theme_element_selected_attributes():
|
||||
|
||||
def test_theme_default_cfg_matches_builtin():
|
||||
|
||||
filename = os.path.join(DEFAULT_THEMES, 'default.cfg.example')
|
||||
filename = os.path.join(Config.DEFAULT_THEMES, 'default.cfg.example')
|
||||
default_theme = Theme.from_file(filename, 'built-in')
|
||||
|
||||
# The default theme file should match the hardcoded values
|
||||
|
||||
264
tuir/config.py
264
tuir/config.py
@@ -13,6 +13,12 @@ from six.moves import configparser
|
||||
from . import docs, __version__
|
||||
from .objects import KeyMap
|
||||
|
||||
|
||||
class Config(object):
|
||||
"""
|
||||
This class manages the loading and saving of configs and other files.
|
||||
"""
|
||||
|
||||
PACKAGE = os.path.dirname(__file__)
|
||||
HOME = os.path.expanduser('~')
|
||||
TEMPLATES = os.path.join(PACKAGE, 'templates')
|
||||
@@ -27,143 +33,13 @@ TOKEN = os.path.join(XDG_DATA_HOME, 'tuir', 'refresh-token')
|
||||
HISTORY = os.path.join(XDG_DATA_HOME, 'tuir', 'history.log')
|
||||
THEMES = os.path.join(XDG_CONFIG_HOME, 'tuir', 'themes')
|
||||
|
||||
|
||||
def build_parser():
|
||||
parser = argparse.ArgumentParser(
|
||||
prog='tuir', description=docs.SUMMARY,
|
||||
epilog=docs.CONTROLS,
|
||||
usage=docs.USAGE,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||
parser.add_argument(
|
||||
'link', metavar='URL', nargs='?',
|
||||
help='[optional] Full URL of a submission to open')
|
||||
parser.add_argument(
|
||||
'-s', dest='subreddit',
|
||||
help='Name of the subreddit that will be loaded on start')
|
||||
parser.add_argument(
|
||||
'-l', dest='link_deprecated',
|
||||
help=argparse.SUPPRESS) # Deprecated, use the positional arg instead
|
||||
parser.add_argument(
|
||||
'--log', metavar='FILE', action='store',
|
||||
help='Log HTTP requests to the given file')
|
||||
parser.add_argument(
|
||||
'--config', metavar='FILE', action='store',
|
||||
help='Load configuration settings from the given file')
|
||||
parser.add_argument(
|
||||
'--ascii', action='store_const', const=True,
|
||||
help='Enable ascii-only mode')
|
||||
parser.add_argument(
|
||||
'--monochrome', action='store_const', const=True,
|
||||
help='Disable color')
|
||||
parser.add_argument(
|
||||
'--theme', metavar='FILE', action='store',
|
||||
help='Color theme to use, see --list-themes for valid options')
|
||||
parser.add_argument(
|
||||
'--list-themes', metavar='FILE', action='store_const', const=True,
|
||||
help='List all of the available color themes')
|
||||
parser.add_argument(
|
||||
'--non-persistent', dest='persistent', action='store_const', const=False,
|
||||
help='Forget the authenticated user when the program exits')
|
||||
parser.add_argument(
|
||||
'--no-autologin', dest='autologin', action='store_const', const=False,
|
||||
help='Do not authenticate automatically on startup')
|
||||
parser.add_argument(
|
||||
'--clear-auth', dest='clear_auth', action='store_const', const=True,
|
||||
help='Remove any saved user data before launching')
|
||||
parser.add_argument(
|
||||
'--copy-config', dest='copy_config', action='store_const', const=True,
|
||||
help='Copy the default configuration to {HOME}/.config/tuir/tuir.cfg')
|
||||
parser.add_argument(
|
||||
'--copy-mailcap', dest='copy_mailcap', action='store_const', const=True,
|
||||
help='Copy an example mailcap configuration to {HOME}/.mailcap')
|
||||
parser.add_argument(
|
||||
'--enable-media', dest='enable_media', action='store_const', const=True,
|
||||
help='Open external links using programs defined in the mailcap config')
|
||||
parser.add_argument(
|
||||
'-V', '--version', action='version', version='tuir ' + __version__)
|
||||
parser.add_argument(
|
||||
'--no-flash', dest='flash', action='store_const', const=False,
|
||||
help='Disable screen flashing')
|
||||
parser.add_argument(
|
||||
'--debug-info', dest='debug_info', action='store_const', const=True,
|
||||
help='Show system and environment information and exit')
|
||||
return parser
|
||||
|
||||
|
||||
def copy_default_mailcap(filename=MAILCAP):
|
||||
"""
|
||||
Copy the example mailcap configuration to the specified file.
|
||||
"""
|
||||
return _copy_settings_file(DEFAULT_MAILCAP, filename, 'mailcap')
|
||||
|
||||
|
||||
def copy_default_config(filename=CONFIG):
|
||||
"""
|
||||
Copy the default tuir user configuration to the specified file.
|
||||
"""
|
||||
return _copy_settings_file(DEFAULT_CONFIG, filename, 'config')
|
||||
|
||||
|
||||
def _copy_settings_file(source, destination, name):
|
||||
"""
|
||||
Copy a file from the repo to the user's home directory.
|
||||
"""
|
||||
|
||||
if os.path.exists(destination):
|
||||
try:
|
||||
ch = six.moves.input(
|
||||
'File %s already exists, overwrite? y/[n]):' % destination)
|
||||
if ch not in ('Y', 'y'):
|
||||
return
|
||||
except KeyboardInterrupt:
|
||||
return
|
||||
|
||||
filepath = os.path.dirname(destination)
|
||||
if not os.path.exists(filepath):
|
||||
os.makedirs(filepath)
|
||||
|
||||
print('Copying default %s to %s' % (name, destination))
|
||||
shutil.copy(source, destination)
|
||||
os.chmod(destination, 0o664)
|
||||
|
||||
|
||||
class OrderedSet(object):
|
||||
"""
|
||||
A simple implementation of an ordered set. A set is used to check
|
||||
for membership, and a list is used to maintain ordering.
|
||||
"""
|
||||
|
||||
def __init__(self, elements=None):
|
||||
elements = elements or []
|
||||
self._set = set(elements)
|
||||
self._list = elements
|
||||
|
||||
def __contains__(self, item):
|
||||
return item in self._set
|
||||
|
||||
def __len__(self):
|
||||
return len(self._list)
|
||||
|
||||
def __getitem__(self, item):
|
||||
return self._list[item]
|
||||
|
||||
def add(self, item):
|
||||
self._set.add(item)
|
||||
self._list.append(item)
|
||||
|
||||
|
||||
class Config(object):
|
||||
"""
|
||||
This class manages the loading and saving of configs and other files.
|
||||
"""
|
||||
|
||||
def __init__(self, history_file=HISTORY, token_file=TOKEN, **kwargs):
|
||||
|
||||
self.history_file = history_file
|
||||
self.token_file = token_file
|
||||
self.config = kwargs
|
||||
|
||||
default, bindings = self.get_file(DEFAULT_CONFIG)
|
||||
default, bindings = self.get_file(self.DEFAULT_CONFIG)
|
||||
self.default = default
|
||||
self.keymap = KeyMap(bindings)
|
||||
|
||||
@@ -245,7 +121,7 @@ class Config(object):
|
||||
"""
|
||||
|
||||
if filename is None:
|
||||
filename = CONFIG
|
||||
filename = Config.CONFIG
|
||||
|
||||
config = configparser.ConfigParser()
|
||||
if os.path.exists(filename):
|
||||
@@ -301,3 +177,127 @@ class Config(object):
|
||||
filepath = os.path.dirname(filename)
|
||||
if not os.path.exists(filepath):
|
||||
os.makedirs(filepath)
|
||||
|
||||
|
||||
def build_parser():
|
||||
parser = argparse.ArgumentParser(
|
||||
prog='tuir', description=docs.SUMMARY,
|
||||
epilog=docs.CONTROLS,
|
||||
usage=docs.USAGE,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||
parser.add_argument(
|
||||
'link', metavar='URL', nargs='?',
|
||||
help='[optional] Full URL of a submission to open')
|
||||
parser.add_argument(
|
||||
'-s', dest='subreddit',
|
||||
help='Name of the subreddit that will be loaded on start')
|
||||
parser.add_argument(
|
||||
'-l', dest='link_deprecated',
|
||||
help=argparse.SUPPRESS) # Deprecated, use the positional arg instead
|
||||
parser.add_argument(
|
||||
'--log', metavar='FILE', action='store',
|
||||
help='Log HTTP requests to the given file')
|
||||
parser.add_argument(
|
||||
'--config', metavar='FILE', action='store',
|
||||
help='Load configuration settings from the given file')
|
||||
parser.add_argument(
|
||||
'--ascii', action='store_const', const=True,
|
||||
help='Enable ascii-only mode')
|
||||
parser.add_argument(
|
||||
'--monochrome', action='store_const', const=True,
|
||||
help='Disable color')
|
||||
parser.add_argument(
|
||||
'--theme', metavar='FILE', action='store',
|
||||
help='Color theme to use, see --list-themes for valid options')
|
||||
parser.add_argument(
|
||||
'--list-themes', metavar='FILE', action='store_const', const=True,
|
||||
help='List all of the available color themes')
|
||||
parser.add_argument(
|
||||
'--non-persistent', dest='persistent', action='store_const', const=False,
|
||||
help='Forget the authenticated user when the program exits')
|
||||
parser.add_argument(
|
||||
'--no-autologin', dest='autologin', action='store_const', const=False,
|
||||
help='Do not authenticate automatically on startup')
|
||||
parser.add_argument(
|
||||
'--clear-auth', dest='clear_auth', action='store_const', const=True,
|
||||
help='Remove any saved user data before launching')
|
||||
parser.add_argument(
|
||||
'--copy-config', dest='copy_config', action='store_const', const=True,
|
||||
help='Copy the default configuration to {HOME}/.config/tuir/tuir.cfg')
|
||||
parser.add_argument(
|
||||
'--copy-mailcap', dest='copy_mailcap', action='store_const', const=True,
|
||||
help='Copy an example mailcap configuration to {HOME}/.mailcap')
|
||||
parser.add_argument(
|
||||
'--enable-media', dest='enable_media', action='store_const', const=True,
|
||||
help='Open external links using programs defined in the mailcap config')
|
||||
parser.add_argument(
|
||||
'-V', '--version', action='version', version='tuir ' + __version__)
|
||||
parser.add_argument(
|
||||
'--no-flash', dest='flash', action='store_const', const=False,
|
||||
help='Disable screen flashing')
|
||||
parser.add_argument(
|
||||
'--debug-info', dest='debug_info', action='store_const', const=True,
|
||||
help='Show system and environment information and exit')
|
||||
return parser
|
||||
|
||||
|
||||
def copy_default_mailcap(filename=Config.MAILCAP):
|
||||
"""
|
||||
Copy the example mailcap configuration to the specified file.
|
||||
"""
|
||||
return _copy_settings_file(Config.DEFAULT_MAILCAP, filename, 'mailcap')
|
||||
|
||||
|
||||
def copy_default_config(filename=Config.CONFIG):
|
||||
"""
|
||||
Copy the default tuir user configuration to the specified file.
|
||||
"""
|
||||
return _copy_settings_file(Config.DEFAULT_CONFIG, filename, 'config')
|
||||
|
||||
|
||||
def _copy_settings_file(source, destination, name):
|
||||
"""
|
||||
Copy a file from the repo to the user's home directory.
|
||||
"""
|
||||
|
||||
if os.path.exists(destination):
|
||||
try:
|
||||
ch = six.moves.input(
|
||||
'File %s already exists, overwrite? y/[n]):' % destination)
|
||||
if ch not in ('Y', 'y'):
|
||||
return
|
||||
except KeyboardInterrupt:
|
||||
return
|
||||
|
||||
filepath = os.path.dirname(destination)
|
||||
if not os.path.exists(filepath):
|
||||
os.makedirs(filepath)
|
||||
|
||||
print('Copying default %s to %s' % (name, destination))
|
||||
shutil.copy(source, destination)
|
||||
os.chmod(destination, 0o664)
|
||||
|
||||
|
||||
class OrderedSet(object):
|
||||
"""
|
||||
A simple implementation of an ordered set. A set is used to check
|
||||
for membership, and a list is used to maintain ordering.
|
||||
"""
|
||||
|
||||
def __init__(self, elements=None):
|
||||
elements = elements or []
|
||||
self._set = set(elements)
|
||||
self._list = elements
|
||||
|
||||
def __contains__(self, item):
|
||||
return item in self._set
|
||||
|
||||
def __len__(self):
|
||||
return len(self._list)
|
||||
|
||||
def __getitem__(self, item):
|
||||
return self._list[item]
|
||||
|
||||
def add(self, item):
|
||||
self._set.add(item)
|
||||
self._list.append(item)
|
||||
|
||||
@@ -14,13 +14,13 @@ from six.moves.urllib.parse import urlparse, parse_qs
|
||||
from six.moves.BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
|
||||
|
||||
from . import docs
|
||||
from .config import TEMPLATES
|
||||
from .config import Config
|
||||
from .exceptions import InvalidRefreshToken
|
||||
from .packages.praw.errors import HTTPException, OAuthException
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
INDEX = os.path.join(TEMPLATES, 'index.html')
|
||||
INDEX = os.path.join(Config.TEMPLATES, 'index.html')
|
||||
|
||||
|
||||
class OAuthHTTPServer(HTTPServer):
|
||||
|
||||
@@ -10,7 +10,7 @@ from contextlib import contextmanager
|
||||
import six
|
||||
from six.moves import configparser
|
||||
|
||||
from .config import THEMES, DEFAULT_THEMES
|
||||
from .config import Config
|
||||
from .exceptions import ConfigError
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
@@ -290,7 +290,7 @@ class Theme(object):
|
||||
self._selected = None
|
||||
|
||||
@classmethod
|
||||
def list_themes(cls, path=THEMES):
|
||||
def list_themes(cls, path=Config.THEMES):
|
||||
"""
|
||||
Compile all of the themes configuration files in the search path.
|
||||
"""
|
||||
@@ -316,13 +316,13 @@ class Theme(object):
|
||||
themes.append(theme)
|
||||
|
||||
themes.extend([Theme(use_color=True), Theme(use_color=False)])
|
||||
load_themes(DEFAULT_THEMES, 'preset')
|
||||
load_themes(Config.DEFAULT_THEMES, 'preset')
|
||||
load_themes(path, 'installed')
|
||||
|
||||
return themes, errors
|
||||
|
||||
@classmethod
|
||||
def print_themes(cls, path=THEMES):
|
||||
def print_themes(cls, path=Config.THEMES):
|
||||
"""
|
||||
Prints a human-readable summary of the installed themes to stdout.
|
||||
|
||||
@@ -363,7 +363,7 @@ class Theme(object):
|
||||
print('')
|
||||
|
||||
@classmethod
|
||||
def from_name(cls, name, path=THEMES):
|
||||
def from_name(cls, name, path=Config.THEMES):
|
||||
"""
|
||||
Search for the given theme on the filesystem and attempt to load it.
|
||||
|
||||
@@ -378,7 +378,7 @@ class Theme(object):
|
||||
if os.path.isfile(filename):
|
||||
return cls.from_file(filename, 'installed')
|
||||
|
||||
filename = os.path.join(DEFAULT_THEMES, '{0}.cfg'.format(name))
|
||||
filename = os.path.join(Config.DEFAULT_THEMES, '{0}.cfg'.format(name))
|
||||
if os.path.isfile(filename):
|
||||
return cls.from_file(filename, 'preset')
|
||||
|
||||
|
||||
Reference in New Issue
Block a user