Skip to content

Commit

Permalink
Merge pull request #1 from moltob/feature/global-context
Browse files Browse the repository at this point in the history
Feature/global context
  • Loading branch information
moltob committed Aug 26, 2017
2 parents d2633a0 + 11a3308 commit 67cc142
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 7 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ python:
- "3.5"
- "3.6"
install:
- pip install --upgrade pip
- pip install --upgrade setuptools
- pip install --upgrade pytest pytest-cov coveralls
- pip install -e .
script:
Expand Down
26 changes: 24 additions & 2 deletions multigen/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,33 @@ def generate_file(self, element, filepath):
class TemplateGenerator(Generator):
templates_path = 'templates'

def __init__(self, global_context=None, **kwargs):
super().__init__(**kwargs)
global_context = global_context or self.create_global_context()

# pass optional global context to tasks:
for task in self.tasks:
task.global_context = global_context

def create_global_context(self, **kwargs):
"""Model-wide code generation context, passed to all templates."""
context = dict(**kwargs)
return context


class TemplateFileTask(Task):
"""Task to generate code via a code-generator template.
Attributes:
template_name: Name of the template to use for this task.
global_context: Template-independent context data, propagated by generator class.
"""
template_name = None
global_context = None

def create_template_context(self, element, **kwargs):
context = dict(element=element)
context.update(**kwargs)
"""Code generation context, specific to template and current element."""
context = dict(element=element, **kwargs)
if self.global_context:
context.update(**self.global_context)
return context
4 changes: 2 additions & 2 deletions multigen/jinja.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ class JinjaGenerator(TemplateGenerator):

def __init__(self, environment=None, **kwargs):
super().__init__(**kwargs)
self.environment = environment or self.create_environment()
environment_ = environment or self.create_environment()

# pass Jinja environment to tasks:
for task in self.tasks:
task.environment = self.environment
task.environment = environment_

def create_environment(self, **kwargs):
"""
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def run_tests(self):

setup(
name='pymultigen',
version='0.1.1',
version='0.2.0',
description='Multi-file frontend for single-file code generators.',
long_description=open('README.rst').read(),
keywords='code generator jinja multi-file',
Expand Down
34 changes: 33 additions & 1 deletion tests/test_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import pytest

from multigen.generator import Generator, Task, TemplateFileTask
from multigen.generator import Generator, Task, TemplateFileTask, TemplateGenerator


def test__generator__generate__no_tasks():
Expand Down Expand Up @@ -37,6 +37,24 @@ def test__generator__generate__tasks():
]


class MyTemplateGenerator(TemplateGenerator):
tasks = [
mock.MagicMock()
]


def test__template_generator__global_context_passed_to_tasks():
generator = MyTemplateGenerator(global_context=mock.sentinel.GLOBAL_CONTEXT)
assert generator.tasks[0].global_context is mock.sentinel.GLOBAL_CONTEXT


@mock.patch.object(TemplateGenerator, 'create_global_context',
side_effect=lambda **kwargs: kwargs)
def test__template_generator__global_context_constructed(mock_create_global_context):
MyTemplateGenerator()
assert mock_create_global_context.call_count == 1


@mock.patch.object(Task, 'ensure_folder')
@mock.patch.object(Task, 'relative_path_for_element', return_value='file.ext')
@mock.patch.object(Task, 'generate_file')
Expand All @@ -50,15 +68,29 @@ def test__task__run(mock_generate_file, mock_relative_path_for_element, mock_ens
mock_generate_file.assert_called_once_with(mock.sentinel.ELEMENT, outfile)


@mock.patch.object(Task, 'ensure_folder')
@mock.patch.object(Task, 'relative_path_for_element', return_value=os.path.abspath('file.ext'))
@mock.patch.object(Task, 'generate_file')
def test__task__run_abspath(mock_generate_file, mock_relative_path_for_element, mock_ensure_folder):
task = Task()
task.run(mock.sentinel.ELEMENT, 'somefolder')

# no concat with with outfolder:
outfile = os.path.abspath('file.ext')
mock_ensure_folder.assert_called_once_with(outfile)


def test__template_task__create_context():
task = TemplateFileTask()
task.global_context = dict(global_key=mock.sentinel.GLOBAL_VALUE)
context = task.create_template_context(
element=mock.sentinel.ELEMENT,
test_key=mock.sentinel.TEST_VALUE
)

assert context['element'] is mock.sentinel.ELEMENT
assert context['test_key'] is mock.sentinel.TEST_VALUE
assert context['global_key'] is mock.sentinel.GLOBAL_VALUE


@pytest.mark.parametrize("factory", [Generator, Task])
Expand Down

0 comments on commit 67cc142

Please sign in to comment.