Compatibility fixes for Blender 2.78c

Blender 2.78c is shipped with a version of the io_blend_utils module that
doesn't have a `pythonpath()` function yet, and that's bundled with an
older version of BAM. To work around this, we ship BAM as wheel, and detect
whether this version is needed to run.

As an added bonus, Blender 2.78c can now also use the file exclude filter
for Flamenco. The `bam_supports_exclude_option()` function is thus no
longer necessary.
This commit is contained in:
Sybren A. Stüvel 2017-06-22 14:43:12 +02:00
parent 7022412889
commit 61fa63eb1d
6 changed files with 43 additions and 36 deletions

View File

@ -1,6 +1,11 @@
# Blender Cloud changelog
## Version 1.7.2 (in development)
- Fixed compatibility with Blender 2.78c.
## Version 1.7.1 (2017-06-13)
- Fixed asyncio issues on Windows

View File

@ -461,16 +461,7 @@ class BlenderCloudPreferences(AddonPreferences):
path_box.prop(self, 'flamenco_job_output_path', text='')
props = path_box.operator('flamenco.explore_file_path', text='', icon='DISK_DRIVE')
props.path = self.flamenco_job_output_path
show_warning = bool(self.flamenco_exclude_filter and
not bam_interface.bam_supports_exclude_option())
job_output_box.alert = show_warning
job_output_box.prop(self, 'flamenco_exclude_filter',
icon='ERROR' if show_warning else 'NONE')
if show_warning:
job_output_box.label(
text='Warning, the exclusion filter requires a newer version of Blender!')
job_output_box.alert = False
job_output_box.prop(self, 'flamenco_exclude_filter')
prop_split = job_output_box.split(0.32, align=True)
prop_split.label('Strip Components:')

View File

@ -1,6 +1,5 @@
"""BAM packing interface for Flamenco."""
import functools
import logging
from pathlib import Path
import typing
@ -15,26 +14,26 @@ class CommandExecutionError(Exception):
pass
if 'bam_supports_exclude_option' in locals():
locals()['bam_supports_exclude_option'].cache_clear()
def wheel_pythonpath_278() -> str:
"""Returns the value of a PYTHONPATH environment variable needed to run BAM from its wheel file.
@functools.lru_cache(maxsize=1)
def bam_supports_exclude_option() -> bool:
"""Returns True if the version of BAM bundled with Blender supports --exclude.
This feature was added to BAM 1.1.7, so we can do a simple version check.
Workaround for Blender 2.78c not having io_blend_utils.pythonpath()
"""
try:
import io_blend_utils
except ImportError:
# If this happens, BAM won't work at all. However, this function can be called from
# the GUI; by being a bit careful while importing, we avoid breaking Blender's GUI.
log.exception('Error importing io_blend_utils module.')
return False
import os
from ..wheels import wheel_filename
return io_blend_utils.bl_info['version'] >= (1, 1, 7)
# Find the wheel to run.
wheelpath = wheel_filename('blender_bam')
log.info('Using wheel %s to run BAM-Pack', wheelpath)
# Update the PYTHONPATH to include that wheel.
existing_pypath = os.environ.get('PYTHONPATH', '')
if existing_pypath:
return os.pathsep.join((existing_pypath, wheelpath))
return wheelpath
async def bam_copy(base_blendfile: Path, target_blendfile: Path,
@ -66,18 +65,20 @@ async def bam_copy(base_blendfile: Path, target_blendfile: Path,
]
if exclusion_filter:
if bam_supports_exclude_option():
args.extend(['--exclude', exclusion_filter])
else:
log.warning('Your version of Blender does not support the exclusion filter, '
'copying all files.')
args.extend(['--exclude', exclusion_filter])
cmd_to_log = ' '.join(shlex.quote(s) for s in args)
log.info('Executing %s', cmd_to_log)
# Workaround for Blender 2.78c not having io_blend_utils.pythonpath()
if hasattr(io_blend_utils, 'pythonpath'):
pythonpath = io_blend_utils.pythonpath()
else:
pythonpath = wheel_pythonpath_278()
proc = await asyncio.create_subprocess_exec(
*args,
env={'PYTHONPATH': io_blend_utils.pythonpath()},
env={'PYTHONPATH': pythonpath},
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,

View File

@ -44,6 +44,12 @@ def load_wheel(module_name, fname_prefix):
module_name, module.__file__, fname_prefix)
return
sys.path.append(wheel_filename(fname_prefix))
module = __import__(module_name)
log.debug('Loaded %s from %s', module_name, module.__file__)
def wheel_filename(fname_prefix: str) -> str:
path_pattern = os.path.join(my_dir, '%s*.whl' % fname_prefix)
wheels = glob.glob(path_pattern)
if not wheels:
@ -51,9 +57,7 @@ def load_wheel(module_name, fname_prefix):
# If there are multiple wheels that match, load the latest one.
wheels.sort()
sys.path.append(wheels[-1])
module = __import__(module_name)
log.debug('Loaded %s from %s', module_name, module.__file__)
return wheels[-1]
def load_wheels():

View File

@ -3,6 +3,7 @@
lockfile==0.12.2
pillarsdk==1.6.1
wheel==0.29.0
blender-bam==1.1.7
# Secondary requirements:
cffi==1.6.0

View File

@ -101,6 +101,11 @@ class BuildWheels(Command):
log.info('Downloading Pillar Python SDK wheel')
self.download_wheel(requirements['pillarsdk'])
# Download BAM from pypi. This is required for compatibility with Blender 2.78.
if not list(self.wheels_path.glob('blender_bam*.whl')):
log.info('Downloading BAM wheel')
self.download_wheel(requirements['blender-bam'])
# Build CacheControl.
if not list(self.wheels_path.glob('CacheControl*.whl')):
log.info('Building CacheControl in %s', self.cachecontrol_path)