Skip to content

Commit

Permalink
working refactor not requiring Flask import from ordbok, doc updates …
Browse files Browse the repository at this point in the history
…needed
  • Loading branch information
eriktaubeneck committed Apr 17, 2015
1 parent 1f47b0b commit 76ab8be
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 150 deletions.
7 changes: 7 additions & 0 deletions ordbok/__init__.py
@@ -0,0 +1,7 @@
from .ordbok import Ordbok
from .config_file import ConfigFile
from .config_env import ConfigEnv
from .config_private import PrivateConfigFile


__all__ = ["Ordbok", "ConfigFile", "ConfigEnv", "PrivateConfigFile"]
6 changes: 3 additions & 3 deletions ordbok/config_env.py
Expand Up @@ -6,7 +6,7 @@
class ConfigEnv(ConfigFile):
def __init__(self, config):
self.config = config
self.keyword = '{}_env_config'.format(self.config.near_miss_key)
self.keyword = '{}_env_config'.format(self.config.namespace)
self.required_keys = []
self.keyword_lookup = {}
self.loaded = False
Expand All @@ -20,9 +20,9 @@ def add_required_key(self, key, value):

def _load(self, _):
environ = {
key.replace(self.config.near_miss_key.upper()+'_', ''): value
key.replace(self.config.namespace.upper()+'_', ''): value
for key, value in os.environ.items() if value and
key.startswith(self.config.near_miss_key.upper())}
key.startswith(self.config.namespace.upper())}
for key, value in environ.items():
self.config[key] = yaml.load(value)

Expand Down
8 changes: 3 additions & 5 deletions ordbok/config_file.py
Expand Up @@ -4,16 +4,14 @@


class ConfigFile(object):
def __init__(self, filename, config=None, envs=None):
def __init__(self, filename, envs=None):
self.filename = filename
self.envs = envs
if config:
self.init_config(config)

def init_config(self, config):
self.config = config
self.keyword = '{}_{}'.format(
self.config.near_miss_key, os.path.splitext(self.filename)[0])
self.config.namespace, os.path.splitext(self.filename)[0])
self.required_keys = []
self.config_file_path = os.path.join(
self.config.config_cwd, self.config.config_dir, self.filename)
Expand Down Expand Up @@ -55,7 +53,7 @@ def _load(self, config_files_lookup):
key, self.filename)
)
if (isinstance(value, six.string_types) and
value.startswith(self.config.near_miss_key)):
value.startswith(self.config.namespace)):
config_files = [k for k in config_files_lookup.keys()
if value.startswith(k)]
if len(config_files) == 0:
Expand Down
59 changes: 16 additions & 43 deletions ordbok/flask_helper.py
@@ -1,46 +1,19 @@
from .ordbok import Ordbok

from flask import Flask as BaseFlask, Config as BaseConfig


class OrdbokFlaskConfig(BaseConfig, Ordbok):
"""
Extented version of the builtin Flask `Config` that inherits
a `from_yaml` method from Ordbok so that config varibables
can be defined there.
"""
def __init__(self, *args, **kwargs):
self.set_defaults(**kwargs)
return super(OrdbokFlaskConfig, self).__init__(*args, **kwargs)

@property
def config_cwd(self):
return self.root_path


def make_config(self, instance_relative=False):
root_path = self.root_path
if instance_relative:
root_path = self.instance_path
return self.config_class(root_path, self.default_config)


def run(self, *args, **kwargs):
if self.config_class is not OrdbokFlaskConfig:
raise Exception(
'Cannot override Flask.run() without using OrdbokFlaskConfig '
'as Flask.config_class.')
if kwargs.get('use_reloader') is not False and self.debug:
kwargs.setdefault('extra_files', [])
kwargs['extra_files'].extend(self.config.config_file_names)
return super(Flask, self).run(*args, **kwargs)


class Flask(BaseFlask):
"""
Extened version of `Flask` that implements the custom config class
defined above.
"""
config_class = OrdbokFlaskConfig
make_config = make_config
run = run
class FlaskOrdbok(Ordbok):
def __init__(self, app=None, **kwargs):
if app:
self.init_app(app)
return super(FlaskOrdbok, self).__init__(**kwargs)

def init_app(self, app):
self._root_path = app.config.root_path

def app_run(self, app, *args, **kwargs):
if kwargs.get('use_reloader') is not False and app.debug:
extra_files = kwargs.get('extra_files', [])
extra_files.extend(self.config_file_names)
if extra_files:
kwargs['extra_files'] = extra_files
return app.run(*args, **kwargs)
59 changes: 27 additions & 32 deletions ordbok/ordbok.py
@@ -1,64 +1,59 @@
import os
import six
from .config_file import ConfigFile
from .util import create_config_file
from .config_env import ConfigEnv


class Ordbok(dict):
def __init__(self, **kwargs):
self.set_defaults(**kwargs)
def __init__(self, config_files=None, config_dir='config',
include_env=True, namespace='ordbok',
default_environment='development', **kwargs):
self.config_files = config_files
if not self.config_files:
self.config_files = ['config.yml', 'local_config.yml']
self.config_dir = config_dir
self.include_env = include_env
self.namespace = namespace
self.default_environment = default_environment
self.loaded = False
return super(Ordbok, self).__init__(**kwargs)

def set_defaults(self, **kwargs):
self.config_files = []
self.config_dir = kwargs.get('config_dir', 'config')
self.custom_config_files = kwargs.get(
'custom_config_files', ['config.yml', 'local_config.yml'])
self.include_env = kwargs.get('include_env', True)
self.near_miss_key = kwargs.get('near_miss_key', 'ordbok')
self.default_environment = kwargs.get(
'default_environment', 'development')

def update_defaults(self, **kwargs):
self.config_dir = kwargs.get('config_dir', self.config_dir)
self.custom_config_files = kwargs.get(
'custom_config_files', self.custom_config_files)
self.include_env = kwargs.get('include_env', self.include_env)
self.near_miss_key = kwargs.get('near_miss_key', self.near_miss_key)
self.default_environment = kwargs.get(
'default_environment', self.default_environment)

@property
def config_cwd(self):
if hasattr(self, '_root_path'):
return self._root_path
return os.getcwd()

@property
def config_file_names(self):
return [getattr(config_file, 'config_file_path', None)
for config_file in self.config_files if
getattr(config_file, 'config_file_path', None)]
return (
[getattr(config_file, 'config_file_path', None)
for config_file in self.config_files if
hasattr(config_file, 'config_file_path')] +
[config_file for config_file in self.config_files if
isinstance(config_file, six.string_types)]
)

def load(self):
if self.loaded:
raise Exception('Ordbok instance can only be loaded once.')
if not self.get('ENVIRONMENT'):
self['ENVIRONMENT'] = os.environ.get(
'{}_ENVIRONMENT'.format(self.near_miss_key.upper()),
'{}_ENVIRONMENT'.format(self.namespace.upper()),
self.default_environment).lower()

self.config_files = [f for f in self.custom_config_files
if isinstance(f, ConfigFile)]
self.config_files = [create_config_file(f) for f in self.config_files]

for f in self.config_files:
f.init_config(self)

self.config_files.extend(
[ConfigFile(f, self) for f in self.custom_config_files
if isinstance(f, six.string_types)])

if self.include_env:
self.config_files.append(ConfigEnv(self))

config_files_lookup = {cf.keyword: cf for cf in self.config_files}
for config_file in self.config_files:
config_file.load(config_files_lookup)
self.loaded = True

@property
def private_file_key(self):
Expand Down
13 changes: 13 additions & 0 deletions ordbok/util.py
@@ -0,0 +1,13 @@
import six
from .config_file import ConfigFile


def create_config_file(f):
if isinstance(f, ConfigFile):
return f
elif isinstance(f, six.string_types):
return ConfigFile(f)
else:
raise TypeError(
'Ordbok.config_files can only be derived from '
'ordbok.ConfigFile or the filename of a config file')
114 changes: 47 additions & 67 deletions tests/base_tests.py
Expand Up @@ -5,10 +5,10 @@
from copy import deepcopy
from yaml.scanner import ScannerError

from flask import Flask as BaseFlask
from flask import Flask

from ordbok.flask_helper import FlaskOrdbok
from ordbok import Ordbok, PrivateConfigFile
from ordbok.flask_helper import (
Flask as OrdbokFlask, OrdbokFlaskConfig, make_config)

from tests.files import (
fudged_config_files, fudged_config_no_local_file,
Expand All @@ -19,8 +19,16 @@ class OrdbokTestCase(unittest.TestCase):
def setUp(self):
self.ordbok = Ordbok()

def test_ordbok_defaults(self):
self.assertEqual(self.ordbok.config_files,
['config.yml', 'local_config.yml'])
self.assertEqual(self.ordbok.config_dir, 'config')
self.assertTrue(self.ordbok.include_env)
self.assertEqual(self.ordbok.namespace, 'ordbok')
self.assertEqual(self.ordbok.default_environment, 'development')

@fudge.patch('six.moves.builtins.open')
def test_ordbok_default(self, fudged_open):
def test_ordbok_load(self, fudged_open):
fudged_open.is_callable().calls(fake_file_factory(fudged_config_files))
self.ordbok.load()
self.assertEquals(self.ordbok['ENVIRONMENT'], 'development')
Expand Down Expand Up @@ -105,8 +113,8 @@ def setUp(self):
self.private_config_file = PrivateConfigFile(
'private_config.yml', envs=['production'])
self.ordbok = Ordbok(
custom_config_files=['config.yml', 'local_config.yml',
self.private_config_file]
config_files=['config.yml', 'local_config.yml',
self.private_config_file]
)

@unittest.skipIf(os.environ.get('SKIP_ENCRYPT_TEST'),
Expand Down Expand Up @@ -161,79 +169,63 @@ def test_ordbok_private_config_no_envs(
self.assertTrue(mock_load_yaml.called)


class OrdbokDefaultsTestCase(OrdbokTestCase):
class OrdbokDefaultsTestCase(unittest.TestCase):
def test_update_all_defaults(self):
self.ordbok.update_defaults(
config_dir='ordbok_config',
custom_config_files=['config.yml'],
include_env=False,
near_miss_key='ordbok_foo',
default_environment='testing',
)
Ordbok(config_dir='ordbok_config',
config_files=['config.yml'],
include_env=False,
namespace='ordbok_foo',
default_environment='testing',)

def test_update_config_dir(self):
self.ordbok.update_defaults(
config_dir='ordbok_config',
)
Ordbok(config_dir='ordbok_config',)

def test_update_custom_config_files(self):
self.ordbok.update_defaults(
custom_config_files=['config.yml'],
)
def test_update_config_files(self):
Ordbok(config_files=['config.yml'],)

def test_update_include_env(self):
self.ordbok.update_defaults(
include_env=False,
)
Ordbok(include_env=False,)

def test_update_near_miss_key(self):
self.ordbok.update_defaults(
near_miss_key='ordbok_foo',
)
def test_update_namespace(self):
Ordbok(namespace='ordbok_foo',)

def test_update_default_environment(self):
self.ordbok.update_defaults(
default_environment='testing',
)
Ordbok(default_environment='testing',)


class FlaskOrdbokTestCase(OrdbokTestCase):
def setUp(self):
self.app = OrdbokFlask(__name__)
self.ordbok = self.app.config
self.ordbok.root_path = os.getcwd() # the fudged files are here

def test_flask_helper(self):
self.assertIsInstance(self.app.config, OrdbokFlaskConfig)
self.app = Flask(os.getcwd()) # fudged files think they are in cwd
self.ordbok = FlaskOrdbok(app=self.app)

def test_flask_reloader(self):
BaseFlask.run = mock.MagicMock(return_value=True)
@mock.patch.object(Flask, 'run')
def test_flask_reloader(self, fudged_flask_run):
self.ordbok.load()
self.app.debug = True
self.app.run()
BaseFlask.run.assert_called()
BaseFlask.run.assert_called_with(
self.ordbok.app_run(self.app)
fudged_flask_run.assert_called()
fudged_flask_run.assert_called_with(
extra_files=self.ordbok.config_file_names)

def test_flask_reloader_debug_off(self):
BaseFlask.run = mock.MagicMock(return_value=True)
@mock.patch.object(Flask, 'run')
def test_flask_reloader_debug_off(self, fudged_flask_run):
self.ordbok.load()
self.app.run()
BaseFlask.run.assert_called()
BaseFlask.run.assert_called_with() # no extra files
self.ordbok.app_run(self.app)
fudged_flask_run.assert_called()
fudged_flask_run.assert_called_with() # no extra files

def test_flask_reloader_use_reloader_false(self):
BaseFlask.run = mock.MagicMock(return_value=True)
@mock.patch.object(Flask, 'run')
def test_flask_reloader_use_reloader_false(self, fudged_flask_run):
self.ordbok.load()
self.app.run(use_reloader=False)
BaseFlask.run.assert_called()
BaseFlask.run.assert_called_with(use_reloader=False) # no extra files
self.ordbok.app_run(self.app, use_reloader=False)
fudged_flask_run.assert_called()
fudged_flask_run.assert_called_with(use_reloader=False) # no extra files


class SpecialFlaskOrbokTestCase(unittest.TestCase):
class SpecialFlaskOrdbokTestCase(unittest.TestCase):
def setUp(self):
self.app = OrdbokFlask(__name__)
self.ordbok = self.app.config
self.app = Flask(__name__)
self.ordbok = FlaskOrdbok(app=self.app)

def test_root_path(self):
"""
Expand All @@ -242,15 +234,3 @@ def test_root_path(self):
this for the the tests.
"""
self.assertEquals(self.app.root_path, self.ordbok.config_cwd)


class BaseFlaskOrdbokTestCase(unittest.TestCase):
def setUp(self):
BaseFlask.config_class = OrdbokFlaskConfig
BaseFlask.make_config = make_config
self.app = BaseFlask(__name__)
self.ordbok = self.app.config
self.ordbok.root_path = os.getcwd() # the fudged files are here

def test_flask_helper(self):
self.assertIsInstance(self.app.config, OrdbokFlaskConfig)

0 comments on commit 76ab8be

Please sign in to comment.