From b6ec1b8fc3fbf1ead5b2e1dfb5087ef85f172abf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= <sybren@stuvel.eu>
Date: Fri, 4 Jan 2019 15:55:19 +0100
Subject: [PATCH] Detect & load RNA overrides file

The 'blender_render' and 'blender_render_progressive' commands now look for
a file named 'thefile-overrides.py' in the same directory as
'thefile.blend'. If it exists, Blender will be told to load that Python
file between loading the blend file and starting the rendering.
---
 flamenco_worker/commands.py           | 30 +++++++++++++++----
 tests/test_commands_blender_render.py | 42 +++++++++++++++++++++++++++
 2 files changed, 66 insertions(+), 6 deletions(-)

diff --git a/flamenco_worker/commands.py b/flamenco_worker/commands.py
index c95ff082..0b7d19bd 100644
--- a/flamenco_worker/commands.py
+++ b/flamenco_worker/commands.py
@@ -740,19 +740,37 @@ class BlenderRenderCommand(AbstractSubprocessCommand):
         return super().validate(settings)
 
     async def execute(self, settings: Settings):
-        cmd = self._build_blender_cmd(settings)
+        cmd = await self._build_blender_cmd(settings)
 
         await self.worker.register_task_update(activity='Starting Blender')
         await self.subprocess(cmd)
 
-    def _build_blender_cmd(self, settings):
+    async def _build_blender_cmd(self, settings):
+        filepath = settings['filepath']
+
         cmd = settings['blender_cmd'][:]
         cmd += [
             '--enable-autoexec',
             '-noaudio',
             '--background',
-            settings['filepath'],
+            filepath,
         ]
+
+        # See if there is an override file to load.
+        try:
+            index = filepath.lower().rindex('.blend')
+        except ValueError:
+            # No '.blend' in the filepath. Weird.
+            pass
+        else:
+            override_filepath = filepath[:index] + '-overrides.py'
+            if Path(override_filepath).exists():
+                msg = f'Override file found in {override_filepath}'
+                self._log.info(msg)
+                await self.worker.register_log(msg)
+
+                cmd.extend(['--python', override_filepath])
+
         if settings.get('python_expr'):
             cmd.extend(['--python-expr', settings['python_expr']])
         if settings.get('render_output'):
@@ -855,8 +873,8 @@ class BlenderRenderProgressiveCommand(BlenderRenderCommand):
         if cycles_chunk < 1:
             return '"cycles_chunk" must be a positive integer'
 
-    def _build_blender_cmd(self, settings):
-        cmd = super()._build_blender_cmd(settings)
+    async def _build_blender_cmd(self, settings):
+        cmd = await super()._build_blender_cmd(settings)
 
         return cmd + [
             '--',
@@ -970,7 +988,7 @@ class BlenderRenderAudioCommand(BlenderRenderCommand):
         if err:
             return err
 
-    def _build_blender_cmd(self, settings: Settings) -> typing.List[str]:
+    async def _build_blender_cmd(self, settings: Settings) -> typing.List[str]:
         frame_start = settings.get('frame_start')
         frame_end = settings.get('frame_end')
         render_output = settings.get('render_output')
diff --git a/tests/test_commands_blender_render.py b/tests/test_commands_blender_render.py
index caa1a560..cf436231 100644
--- a/tests/test_commands_blender_render.py
+++ b/tests/test_commands_blender_render.py
@@ -1,5 +1,6 @@
 from pathlib import Path
 import subprocess
+import tempfile
 from unittest import mock
 
 from unittest.mock import patch
@@ -152,3 +153,44 @@ class BlenderRenderTest(AbstractCommandTest):
                 stdout=subprocess.PIPE,
                 stderr=subprocess.STDOUT,
             )
+
+    def test_cli_args_override_file(self):
+        """Test that an override file next to the blend file is recognised."""
+        from tests.mock_responses import CoroMock
+
+        with tempfile.TemporaryDirectory() as tempdir:
+            temppath = Path(tempdir)
+
+            blendpath = temppath / 'thefile.blend'
+            blendpath.touch()
+            override = temppath / 'thefile-overrides.py'
+            override.touch()
+
+            settings = {
+                # Point blender_cmd to this file so that we're sure it exists.
+                'blender_cmd': __file__,
+                'chunk_size': 100,
+                'frames': '1..2',
+                'format': 'JPEG',
+                'filepath': str(blendpath),
+            }
+
+            cse = CoroMock(...)
+            cse.coro.return_value.wait = CoroMock(return_value=0)
+            cse.coro.return_value.pid = 47
+            with patch('asyncio.create_subprocess_exec', new=cse) as mock_cse:
+                self.loop.run_until_complete(self.cmd.run(settings))
+
+                mock_cse.assert_called_once_with(
+                    __file__,
+                    '--enable-autoexec',
+                    '-noaudio',
+                    '--background',
+                    str(blendpath),
+                    '--python', str(override),
+                    '--render-format', 'JPEG',
+                    '--render-frame', '1..2',
+                    stdin=subprocess.DEVNULL,
+                    stdout=subprocess.PIPE,
+                    stderr=subprocess.STDOUT,
+                )
-- 
GitLab