Skip to content

Commit

Permalink
Add templating functionality to external configs
Browse files Browse the repository at this point in the history
  • Loading branch information
JakobGM committed Feb 28, 2018
1 parent 8098d60 commit a5ac966
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 67 deletions.
2 changes: 1 addition & 1 deletion astrality/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def jinja_environment(
logger = logging.getLogger(__name__)
LoggingUndefined = make_logging_undefined(
logger=logger,
base=Undefined
base=Undefined,
)

env = Environment(
Expand Down
61 changes: 35 additions & 26 deletions astrality/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,12 @@ def insert_into(
f'Importing context section {section} from {str(from_config_file)}',
)

# Context files do not insert context values, as that would cause a lot
# of complexity for end users. Old context values will be inserted
# for placeholders, etc.
contexts = compiler.context(dict_from_config_file(
from_config_file,
context={}, # TODO
context={},
))

if section and from_section:
Expand Down Expand Up @@ -284,6 +287,7 @@ class EnablingStatement(EnablingStatementRequired, total=False):
class ModuleSource(ABC):
directory: Path
config_file: Path
_config: Dict[Any, Any]

@abstractmethod
def __init__(
Expand All @@ -300,9 +304,8 @@ def name_syntax(self) -> Pattern:
"""Regular expression defining how to name this type of module source."""
raise NotImplementedError

@property
@abstractmethod
def config(self) -> Dict[Any, Any]:
def config(self, context: Dict[str, Resolver]) -> Dict[Any, Any]:
"""Return the dictionary containing the module configuration."""
raise NotImplementedError

Expand Down Expand Up @@ -346,8 +349,7 @@ def __init__(
assert modules_directory.is_absolute()
self.directory = modules_directory

@property
def config(self) -> Dict[Any, Any]:
def config(self, context: Dict[str, Resolver]) -> Dict[Any, Any]:
"""Return configuration related to global module (TODO)."""
return {}

Expand Down Expand Up @@ -402,8 +404,7 @@ def __init__(
self.directory = modules_directory / self.github_user / self.github_repo
self.config_file = self.directory / 'config.yml'

@property
def config(self) -> Dict[Any, Any]:
def config(self, context: Dict[str, Resolver]) -> Dict[Any, Any]:
"""Return the contents of config.yml, filtering out disabled modules."""
if hasattr(self, '_config'):
return self._config
Expand All @@ -425,6 +426,7 @@ def config(self) -> Dict[Any, Any]:

self._config = filter_config_file(
config_file=self.config_file,
context=context,
enabled_module_name=self.enabled_module_name,
prepend=f'github::{self.github_user}/{self.github_repo}::',
)
Expand All @@ -433,23 +435,23 @@ def config(self) -> Dict[Any, Any]:

def __contains__(self, module_name: str) -> bool:
"""Return True if GitHub module repo is enabled."""
return 'module/' + module_name in self.config
return 'module/' + module_name in self._config

def __eq__(self, other) -> bool:
"""
Return True if two GithubModuleSource objects represent the same
directory with identical modules enabled.
"""
try:
return self.directory == other.directory and self.config == other.config
return self.directory == other.directory and self._config == other._config
except AttributeError:
return False



def __repr__(self) -> str:
return f"GithubModuleSource('{self.github_user}/{self.github_repo}')" \
f' = {tuple(self.config.keys())}'
f' = {tuple(self._config.keys())}'


class DirectoryModuleSource(ModuleSource):
Expand Down Expand Up @@ -481,12 +483,12 @@ def __init__(
self.config_file = self.directory / 'config.yml'
self.trusted = enabling_statement.get('trusted', True)

@property
def config(self) -> Dict[Any, Any]:
def config(self, context: Dict[str, Resolver]) -> Dict[Any, Any]:
"""Return the module configuration defined in directory."""
if not hasattr(self, '_config'):
self._config = filter_config_file(
config_file=self.config_file,
context=context,
enabled_module_name=self.enabled_module_name,
prepend=str(self.relative_directory_path) + '::',
)
Expand All @@ -510,7 +512,7 @@ def __eq__(self, other) -> bool:

def __contains__(self, module_name: str) -> bool:
"""Return True if source contains module named `module_name`."""
return 'module/' + module_name in self.config
return 'module/' + module_name in self._config


class EnabledModules:
Expand Down Expand Up @@ -605,6 +607,18 @@ def module_directories(within: Path) -> Tuple[str, ...]:
)
return ()

def compile_config_files(
self,
context: Dict[str, Resolver],
):
"""Compile all config templates with context."""
for source in (
*self.source_types[DirectoryModuleSource],
*self.source_types[GithubModuleSource],
):
source.config(context=context)


def __contains__(self, module_name: str) -> bool:
"""Return True if the given module name is supposed to be enabled."""
if module_name[:7].lower() == 'module/':
Expand Down Expand Up @@ -697,22 +711,17 @@ def external_module_config_files(self) -> Iterable[Path]:
for external_module_source in self.external_module_sources:
yield external_module_source.config_file

def module_configs_dict(self) -> ModuleConfig:
"""
Return a merged dictionary of all directory module configs.
TODO: Should at some point be responsible to return *all* module
config dicts.
"""
module_config_dict: ModuleConfig = {}
for external_module_source in self.external_module_sources:
module_config_dict.update(external_module_source.config)

return module_config_dict
def compile_config_files(
self,
context: Dict[str, Resolver],
):
"""Compile all config templates with context."""
self.enabled_modules.compile_config_files(context)


def filter_config_file(
config_file: Path,
context: Dict[str, Resolver],
enabled_module_name: str,
prepend: str,
) -> ModuleConfig:
Expand All @@ -725,7 +734,7 @@ def filter_config_file(
try:
modules_dict = dict_from_config_file(
config_file=config_file,
context={}, # TODO
context=context,
)
except FileNotFoundError:
logger.warning(
Expand Down
9 changes: 7 additions & 2 deletions astrality/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -353,11 +353,16 @@ def __init__(self, config: ApplicationConfig) -> None:

self.modules: Dict[str, Module] = {}

# Application context is used in compiling external config sources
application_context = context(config)

# Insert externally managed modules
for external_module_source in self.global_modules_config.external_module_sources:
module_directory = external_module_source.directory

module_configs = external_module_source.config
module_configs = external_module_source.config(
context=application_context,
)

# Insert context defined in external configuration
self.application_context.update(context(module_configs))
Expand All @@ -380,7 +385,7 @@ def __init__(self, config: ApplicationConfig) -> None:

# Update the context from `astrality.yml`, overwriting any defined
# contexts in external modules in the case of naming conflicts
self.application_context.update(context(config))
self.application_context.update(application_context)

# Insert modules defined in `astrality.yml`
for section, options in config.items():
Expand Down
27 changes: 25 additions & 2 deletions astrality/tests/config/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,5 +211,28 @@ def test_get_user_configuration(self, dir_with_compilable_files):
assert user_conf['key1'] == 'test_value'
assert user_conf['key2'] == 'test'

def test_module_source(self):
pass
def test_module_directory_source(
self,
test_config_directory,
default_global_options,
_runtime,
):
application_config = {
'config/modules': {
'modules_directory': 'test_modules',
'enabled_modules': [
{'name': 'module_with_placeholders::*'},
],
},
'context/module': {
'setting': 'hi',
},
}
application_config.update(default_global_options)
application_config.update(_runtime)

module_manager = ModuleManager(application_config)
module_config = module_manager.modules['module_with_placeholders::placeholders'].module_config

assert module_config['hi'] == 'bye!'
assert module_config['test_value'] == 'test'

0 comments on commit a5ac966

Please sign in to comment.