Skip to content
This repository has been archived by the owner on Jan 14, 2024. It is now read-only.

Commit

Permalink
#29: Jinja2: Allow to use variables in filenames (--template-filenames)
Browse files Browse the repository at this point in the history
  • Loading branch information
blackandred committed Jul 20, 2020
1 parent a1e7dc5 commit 9f5a2e3
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 8 deletions.
4 changes: 3 additions & 1 deletion docs/source/standardlib/jinja.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ Renders a single file from JINJA2.
Renders all files recursively in given directory to other directory.
Can remove source files after rendering them to the output files.

*Pattern is a regexp pattern that matches whole path, not only file name*
*Note: Pattern is a regexp pattern that matches whole path, not only file name*

*Note: Exclude pattern is matching on SOURCE files, not on target files*


**Example usage:**
Expand Down
14 changes: 14 additions & 0 deletions src/rkd/standardlib/jinja.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ def execute(self, context: ExecutionContext) -> bool:
pattern = re.compile(context.get_arg('--pattern'))
exclude_pattern = re.compile(context.get_arg('--exclude-pattern')) if context.get_arg('--exclude-pattern') else None
copy_not_matched = context.get_arg('--copy-not-matching-files')
template_filenames = context.get_arg('--template-filenames')

self.io().info_msg('Pattern is `%s`' % context.get_arg('--pattern'))

Expand All @@ -85,6 +86,9 @@ def execute(self, context: ExecutionContext) -> bool:
if target_full_path.endswith('.j2'):
target_full_path = target_full_path[:-3]

if template_filenames:
target_full_path = self.replace_vars_in_filename(context.env, target_full_path)

if exclude_pattern and self._is_file_matching_filter(exclude_pattern, source_full_path):
self.io().info_msg('Skipping file "%s" - (filtered out by --exclude-pattern)' % source_full_path)
continue
Expand All @@ -110,6 +114,13 @@ def execute(self, context: ExecutionContext) -> bool:

return True

@staticmethod
def replace_vars_in_filename(env_vars: dict, filename: str) -> str:
for name, value in env_vars.items():
filename = filename.replace('--%s--' % name, value)

return filename

def _copy_file(self, source_full_path: str, target_full_path: str):
self.sh('mkdir -p "%s"' % os.path.dirname(target_full_path))
self.sh('cp -p "%s" "%s"' % (source_full_path, target_full_path))
Expand Down Expand Up @@ -140,6 +151,9 @@ def configure_argparse(self, parser: ArgumentParser):
parser.add_argument('--exclude-pattern', '-xp', help='Optional regexp for a pattern exclude, to exclude files')
parser.add_argument('--copy-not-matching-files', '-c', help='Copy all files that are not matching the pattern' +
' instead of skipping them', action='store_true')
parser.add_argument('--template-filenames', '-tf',
help='Replace variables in filename eg. --VAR--, ' +
'where VAR is a name of environment variable', action='store_true')


def imports():
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Hijo del pueblo, te oprimen cadenas,
y esa injusticia no puede seguir;
si tu existencia es un mundo de penas
antes que esclavo prefiere morir.
En la batalla, la hiena fascista.
por nuestro esfuerzo sucumbirá;
y el pueblo entero, con los anarquistas,
hará que triunfe la libertad.

Trabajador, no más sufrir,
el opresor ha de sucumbir.
Levántate, pueblo leal,
al grito de revolución social.
Fuerte unidad de fe y de acción
producirá la revolución.
Nuestro pendón uno ha de ser:
sólo en la unión está el vencer.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Negras tormentas agitan los aires,
nubes oscuras nos impiden ver.
Aunque nos espere el dolor y la muerte,
contra el enemigo nos llama el deber.

El bien más preciado
es la libertad,
hay que defenderla con fe y con valor.
Alta la bandera revolucionaria,
que llevará al pueblo a la emancipación

En pie el pueblo obrero a la batalla,
hay que derrocar a la reacción.
¡A las Barricadas!
¡A las Barricadas!
por el triunfo de la Confederación.
75 changes: 68 additions & 7 deletions test/test_standardlib_jinja_render_directory.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
#!/usr/bin/env python3

import os
import unittest
from rkd.standardlib.jinja import RenderDirectoryTask
from rkd.test import mock_task, mock_execution_context

TESTS_DIR = os.path.dirname(os.path.realpath(__file__))


class TestRenderDirectoryTask(unittest.TestCase):
"""Tests for a task that should render JINJA2 files from DIRECTORY "A" to DIRECTORY "B"
"""

@staticmethod
def _execute_mocked_task(params: dict) -> tuple:
def _execute_mocked_task(params: dict, env: dict = {}) -> tuple:
task: RenderDirectoryTask = RenderDirectoryTask()
mock_task(task)

Expand All @@ -30,7 +33,7 @@ def mock__sh(*args, **kwargs):
task._delete_file = lambda file: deletions.append(file)

# run task
task.execute(mock_execution_context(task, params))
task.execute(mock_execution_context(task, params, env))

return calls, deletions

Expand All @@ -46,7 +49,8 @@ def test_iterates_over_subdirectories_including_depth_and_pattern(self):
'delete_source_files': False,
'pattern': '(.*)(src|test)/(.*).py$',
'--exclude-pattern': '',
'--copy-not-matching-files': False
'--copy-not-matching-files': False,
'--template-filenames': False
})

# example files (please correct if changed in filesystem)
Expand All @@ -71,7 +75,8 @@ def test_files_are_copied_when_not_matching_pattern_but_switch_was_used(self):
'delete_source_files': False,
'pattern': '(.*).j2',
'--exclude-pattern': '(.*).pyc',
'--copy-not-matching-files': True
'--copy-not-matching-files': True,
'--template-filenames': False
})

flatten_list_as_str = ' '.join(renderings)
Expand All @@ -94,7 +99,8 @@ def test_without_pattern(self):
'delete_source_files': False,
'pattern': '',
'--exclude-pattern': '',
'--copy-not-matching-files': False
'--copy-not-matching-files': False,
'--template-filenames': False
})

# example files (please correct if changed in filesystem)
Expand All @@ -109,7 +115,8 @@ def test_no_files_deleted_when_option_disabled(self):
'delete_source_files': False,
'pattern': '',
'--exclude-pattern': '',
'--copy-not-matching-files': False
'--copy-not-matching-files': False,
'--template-filenames': False
})

self.assertEqual([], deletions)
Expand All @@ -121,7 +128,61 @@ def test_files_are_called_to_be_deleted(self):
'delete_source_files': True,
'pattern': '(.*)test_standardlib_jinja_render_directory.py$',
'--exclude-pattern': '',
'--copy-not-matching-files': False
'--copy-not-matching-files': False,
'--template-filenames': False
})

self.assertEqual(['../test/test_standardlib_jinja_render_directory.py'], deletions)

def test_replace_vars_in_filename(self):
name = RenderDirectoryTask().replace_vars_in_filename({'Word': 'triumph'}, 'that-agony-is-your---Word--.txt')

self.assertEqual('that-agony-is-your-triumph.txt', name)

def test_replace_vars_in_filename_multiple_occurrences(self):
name = RenderDirectoryTask()\
.replace_vars_in_filename({'word': 'pueblo', 'word2': 'hijos'}, '--word2--_del_--word--(--word--_version)')

self.assertEqual('hijos_del_pueblo(pueblo_version)', name)

def test_filename_templating_when_switch_is_on(self):
"""Assert that variables in filenames are also replaced, not only in the content
Condition: When the "--template-filenames" is used
"""

renderings, deletions = self._execute_mocked_task({
'source': TESTS_DIR + '/internal-samples/jinja2-filename-templating',
'target': '/tmp',
'delete_source_files': True,
'pattern': '(.*).j2',
'--exclude-pattern': '',
'--copy-not-matching-files': True,
'--template-filenames': True
}, env={
'song_name': 'hijos-del-pueblo',
'song2_name': 'a-las-barricadas'
})

self.assertIn('-> "/tmp//lyrics-hijos-del-pueblo.txt"', ' '.join(renderings),
msg='Expected that the matching .j2 file would have changed name')
self.assertIn('"/tmp//lyrics2-a-las-barricadas.txt"', ' '.join(renderings),
msg='Expected that the non-j2 file would have also changed name')

def test_filename_templating_is_not_replacing_vars_when_switch_is_not_used(self):
"""Checks if the variable replacing in filenames can be turned off by not using
"--template-filenames" switch"""

renderings, deletions = self._execute_mocked_task({
'source': TESTS_DIR + '/internal-samples/jinja2-filename-templating',
'target': '/tmp',
'delete_source_files': True,
'pattern': '(.*).j2',
'--exclude-pattern': '',
'--copy-not-matching-files': False,
'--template-filenames': False
}, env={
'song_name': 'hijos-del-pueblo'
})

self.assertIn('-> "/tmp//lyrics---song_name--.txt"', ' '.join(renderings))

0 comments on commit 9f5a2e3

Please sign in to comment.