Skip to content

Commit

Permalink
Merge pull request #665 from praw-dev/config
Browse files Browse the repository at this point in the history
Extra praw.ini config values are now available under Config.custom.
  • Loading branch information
bboe committed Aug 27, 2016
2 parents 99456d1 + 9313b33 commit 079b5ee
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 33 deletions.
83 changes: 50 additions & 33 deletions praw/config.py
Expand Up @@ -23,6 +23,12 @@ class Config(object):
CONFIG = None
CONFIG_NOT_SET = _NotSet() # Represents a config value that is not set.

@staticmethod
def _config_boolean(item):
if isinstance(item, bool):
return item
return item.lower() in {'1', 'yes', 'true', 'on'}

@classmethod
def _load_config(cls):
"""Attempt to load settings from various praw.ini files."""
Expand All @@ -42,45 +48,56 @@ def _load_config(cls):
config.read(locations)
cls.CONFIG = config

@property
def short_url(self):
"""Return the short url or raise a ClientException when not set."""
if self._short_url is self.CONFIG_NOT_SET:
raise ClientException('No short domain specified.')
return self._short_url

def __init__(self, site_name, **settings):
"""Initialize a Config instance."""
def config_boolean(item):
if isinstance(item, bool):
return item
return item.lower() in {'1', 'yes', 'true', 'on'}

def fetch_or_not_set(key):
if key in settings: # Passed in values have the highest priority
return raw[key]
return os.getenv('praw_{}'.format(key)) or raw.get(key) \
or self.CONFIG_NOT_SET

if Config.CONFIG is None:
self._load_config()

raw = dict(Config.CONFIG.items(site_name), **settings)
self._settings = settings
self.custom = dict(Config.CONFIG.items(site_name), **settings)

self._initialize_attributes()

def _fetch(self, key):
value = self.custom[key]
del self.custom[key]
return value

self._short_url = raw.get('short_url') or self.CONFIG_NOT_SET
self.check_for_updates = config_boolean(
fetch_or_not_set('check_for_updates'))
self.client_id = fetch_or_not_set('client_id')
self.client_secret = fetch_or_not_set('client_secret')
self.http_proxy = fetch_or_not_set('http_proxy')
self.https_proxy = fetch_or_not_set('https_proxy')
self.kinds = {x: raw['{}_kind'.format(x)] for x in
def _fetch_default(self, key, default=None):
if key not in self.custom:
return default
return self._fetch(key)

def _fetch_or_not_set(self, key):
if key in self._settings: # Passed in values have the highest priority
return self._fetch(key)

env_value = os.getenv('praw_{}'.format(key))
ini_value = self._fetch_default(key) # Needed to remove from custom

# Environment variables have higher priority than praw.ini settings
return env_value or ini_value or self.CONFIG_NOT_SET

def _initialize_attributes(self):
self._short_url = self._fetch_default('short_url') \
or self.CONFIG_NOT_SET
self.check_for_updates = self._config_boolean(
self._fetch_or_not_set('check_for_updates'))
self.kinds = {x: self._fetch('{}_kind'.format(x)) for x in
['comment', 'message', 'redditor', 'submission',
'subreddit']}
self.oauth_url = raw['oauth_url']
self.reddit_url = raw['reddit_url']
self.redirect_uri = fetch_or_not_set('redirect_uri')
self.refresh_token = fetch_or_not_set('refresh_token')
self.password = fetch_or_not_set('password')
self.user_agent = fetch_or_not_set('user_agent')
self.username = fetch_or_not_set('username')

@property
def short_url(self):
"""Return the short url or raise a ClientException when not set."""
if self._short_url is self.CONFIG_NOT_SET:
raise ClientException('No short domain specified.')
return self._short_url
for attribute in ('client_id', 'client_secret', 'http_proxy',
'https_proxy', 'redirect_uri', 'refresh_token',
'password', 'user_agent', 'username'):
setattr(self, attribute, self._fetch_or_not_set(attribute))

for required_attribute in ('oauth_url', 'reddit_url'):
setattr(self, required_attribute, self._fetch(required_attribute))
8 changes: 8 additions & 0 deletions tests/unit/test_config.py
Expand Up @@ -41,6 +41,14 @@ def test_check_for_updates__false(self):
config = Config('DEFAULT', check_for_updates=value)
assert config.check_for_updates is False

def test_custom__extra_values_set(self):
config = Config('DEFAULT', user1='foo', user2='bar')
assert config.custom == {'user1': 'foo', 'user2': 'bar'}

def test_custom__no_extra_values_set(self):
config = Config('DEFAULT')
assert config.custom == {}

def test_check_for_updates__true(self):
for value in [True, '1', 'true', 'YES', 'on']:
config = Config('DEFAULT', check_for_updates=value)
Expand Down

0 comments on commit 079b5ee

Please sign in to comment.