[Bf-extensions-cvs] [415c234] master: io_blend_utils: ship BAM as wheel file, running BAM-pack from that

Sybren A. Stüvel noreply at git.blender.org
Tue Jan 17 17:29:42 CET 2017


Commit: 415c234d1bd355dc6e59e4e1370e0523835e4862
Author: Sybren A. Stüvel
Date:   Tue Jan 17 16:32:49 2017 +0100
Branches: master
https://developer.blender.org/rBA415c234d1bd355dc6e59e4e1370e0523835e4862

io_blend_utils: ship BAM as wheel file, running BAM-pack from that

Previously we had a copy of BAM's blendfile_pack.py shipped with Blender.
Updating that was cumbersome, as changes in one copy would have to be
manually ported to the other. This is now resolved by not bundling
blendfile_pack.py at all, but to include BAM as wheel file. This wheel
file can be produced by running "python3 setup.py bdist_wheel" in the BAM
source directory, and can be bundled with Blender without further
modification.

Blender looks for a file "blender_bam-*.whl" in the io_blend_utils
directory, and loads the (alphabetically) last version. Even though there
should be only one wheel file bundled, things won't break when there happen
to be more, and Blender should pick up on the latest version (given simple
versioning schemes).

===================================================================

A	io_blend_utils/README.md
M	io_blend_utils/__init__.py
M	io_blend_utils/bl_utils/subprocess_helper.py
A	io_blend_utils/blender_bam-1.1.1-py3-none-any.whl
D	io_blend_utils/blendfile_pack.py

===================================================================

diff --git a/io_blend_utils/README.md b/io_blend_utils/README.md
new file mode 100644
index 0000000..459a5f4
--- /dev/null
+++ b/io_blend_utils/README.md
@@ -0,0 +1,25 @@
+
+Bundling BAM with Blender
+-------------------------
+
+Blender is bundled with a version of [BAM](https://pypi.python.org/pypi/blender-bam/).
+To update this version, first build a new `wheel <http://pythonwheels.com/>`_ file in
+BAM itself:
+
+    python3 setup.py bdist_wheel
+
+Then copy this wheel to Blender:
+
+    cp dist/blender_bam-xxx.whl /path/to/blender/release/scripts/addons/io_blend_utils/
+
+Remove old wheels that are still in `/path/to/blender/release/scripts/addons/io_blend_utils/`
+before committing.
+
+
+Running bam-pack from the wheel
+-------------------------------
+
+This is the way that Blender runs bam-pack:
+
+    PYTHONPATH=./path/to/blender_bam-xxx.whl python3 -m bam.pack
+
diff --git a/io_blend_utils/__init__.py b/io_blend_utils/__init__.py
index adbd2d0..d6f3c26 100644
--- a/io_blend_utils/__init__.py
+++ b/io_blend_utils/__init__.py
@@ -18,8 +18,8 @@
 
 bl_info = {
     "name": "Blend File Utils",
-    "author": "Campbell Barton",
-    "version": (0, 1),
+    "author": "Campbell Barton and Sybren A. Stüvel",
+    "version": (1, 0),
     "blender": (2, 76, 0),
     "location": "File > External Data > Blend Utils",
     "description": "Utility for packing blend files",
@@ -27,8 +27,9 @@ bl_info = {
     "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/Import-Export/BlendFile_Utils",
     "support": 'OFFICIAL',
     "category": "Import-Export",
-    }
+}
 
+import logging
 
 import bpy
 from bpy.types import Operator
@@ -41,6 +42,7 @@ class ExportBlendPack(Operator, ExportHelper, SubprocessHelper):
     """Packs a blend file and all its dependencies into an archive for easy redistribution"""
     bl_idname = "export_blend.pack"
     bl_label = "Pack Blend to Archive"
+    log = logging.getLogger('%s.ExportBlendPack' % __name__)
 
     # ExportHelper
     filename_ext = ".zip"
@@ -55,22 +57,26 @@ class ExportBlendPack(Operator, ExportHelper, SubprocessHelper):
         return bpy.data.is_saved
 
     def process_pre(self):
-        import os
         import tempfile
 
         self.temp_dir = tempfile.TemporaryDirectory()
 
-        filepath_blend = bpy.data.filepath
-
+        self.environ = {'PYTHONPATH': pythonpath()}
+        self.outfname = bpy.path.ensure_ext(self.filepath, ".zip")
         self.command = (
             bpy.app.binary_path_python,
-            os.path.join(os.path.dirname(__file__), "blendfile_pack.py"),
+            '-m', 'bam.pack',
             # file to pack
-            "--input", filepath_blend,
+            "--input", bpy.data.filepath,
             # file to write
-            "--output", bpy.path.ensure_ext(self.filepath, ".zip"),
+            "--output", self.outfname,
             "--temp", self.temp_dir.name,
-            )
+        )
+
+        if self.log.isEnabledFor(logging.INFO):
+            import shlex
+            cmd_to_log = ' '.join(shlex.quote(s) for s in self.command)
+            self.log.info('Executing %s', cmd_to_log)
 
     def process_post(self, returncode):
         if self.temp_dir is not None:
@@ -79,6 +85,7 @@ class ExportBlendPack(Operator, ExportHelper, SubprocessHelper):
             except:
                 import traceback
                 traceback.print_exc()
+        self.log.info('Written to %s', self.outfname)
 
 
 def menu_func(self, context):
@@ -89,7 +96,30 @@ def menu_func(self, context):
 
 classes = (
     ExportBlendPack,
-    )
+)
+
+
+def pythonpath() -> str:
+    """Returns the value of a PYTHONPATH environment variable needed to run BAM from its wheel file.
+    """
+
+    import os.path
+    import glob
+
+    log = logging.getLogger('%s.pythonpath' % __name__)
+
+    # Find the wheel to run.
+    my_dir = os.path.abspath(os.path.dirname(__file__))
+    wheelpaths = glob.glob(os.path.join(my_dir, 'blender_bam-*.whl'))
+    wheelpath = sorted(wheelpaths)[-1]  # use the last version we find, should be only one.
+    log.info('Using wheel file %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
 
 
 def register():
diff --git a/io_blend_utils/bl_utils/subprocess_helper.py b/io_blend_utils/bl_utils/subprocess_helper.py
index 024f0da..ef9c602 100644
--- a/io_blend_utils/bl_utils/subprocess_helper.py
+++ b/io_blend_utils/bl_utils/subprocess_helper.py
@@ -22,6 +22,7 @@
 Defines an operator mix-in to use for non-blocking command line access.
 """
 
+
 class SubprocessHelper:
     """
     Mix-in class for operators to run commands in a non-blocking way.
@@ -39,8 +40,18 @@ class SubprocessHelper:
         ``process_post(returncode)``:
             Callback that runs when the process has ende.
             returncode is -1 if the process was terminated.
+
+    Subclass may define:
+        ``environment``:
+            Dict of environment variables exposed to the subprocess.
+            Contrary to the subprocess.Popen(env=...) parameter, this
+            dict is and not used to replace the existing environment
+            entirely, but is just used to update it.
     """
 
+    environ = {}
+    command = ()
+
     @staticmethod
     def _non_blocking_readlines(f, chunk=64):
         """
@@ -138,14 +149,20 @@ class SubprocessHelper:
 
     def execute(self, context):
         import subprocess
+        import os
+        import copy
 
         self.process_pre()
 
+        env = copy.deepcopy(os.environ)
+        env.update(self.environ)
+
         try:
             p = subprocess.Popen(
                     self.command,
                     stdout=subprocess.PIPE,
                     stderr=subprocess.PIPE,
+                    env=env,
                     )
         except FileNotFoundError as ex:
             # Command not found
diff --git a/io_blend_utils/blender_bam-1.1.1-py3-none-any.whl b/io_blend_utils/blender_bam-1.1.1-py3-none-any.whl
new file mode 100644
index 0000000..e422f63
Binary files /dev/null and b/io_blend_utils/blender_bam-1.1.1-py3-none-any.whl differ
diff --git a/io_blend_utils/blendfile_pack.py b/io_blend_utils/blendfile_pack.py
deleted file mode 100755
index dee2bfa..0000000
--- a/io_blend_utils/blendfile_pack.py
+++ /dev/null
@@ -1,612 +0,0 @@
-#!/usr/bin/env python3
-
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-#
-# ***** END GPL LICENCE BLOCK *****
-
-from blend import blendfile_path_walker
-
-TIMEIT = False
-
-
-# ----------------------
-# debug low level output
-#
-# ... when internals _really_ fail & we want to know why
-def _dbg(text):
-    import sys
-    from utils.system import colorize
-    if type(text) is bytes:
-        text = text.decode('utf-8')
-    sys.__stdout__.write(colorize(text, color='red') + "\n")
-    sys.__stdout__.flush()
-
-
-def _relpath_remap(
-        path_src,
-        base_dir_src,
-        fp_basedir,
-        blendfile_src_dir_fakeroot,
-        ):
-
-    import os
-
-    if not os.path.isabs(path_src):
-        # Absolute win32 paths on a unix system
-        # cause bad issues!
-        if len(path_src) >= 2:
-            if path_src[0] != b'/'[0] and path_src[1] == b':'[0]:
-                pass
-            else:
-                raise Exception("Internal error 'path_src' -> %r must be absolute" % path_src)
-
-    path_src = os.path.normpath(path_src)
-    if os.name != "nt":
-        path_dst = os.path.relpath(path_src, base_dir_src)
-    else:
-        # exception for windows, we need to support mapping between drives
-        try:
-            path_dst = os.path.relpath(path_src, base_dir_src)
-        except ValueError:
-            # include the absolute path when the file is on a different drive.
-            path_dst = os.path.relpath(
-                    os.path.join(base_dir_src, b'__' + path_src.replace(b':', b'\\')),
-                    base_dir_src,
-                    )
-
-    if blendfile_src_dir_fakeroot is None:
-        # /foo/../bar.png --> /foo/__/bar.png
-        path_dst = path_dst.replace(b'..', b'__')
-        path_dst = os.path.normpath(path_dst)
-    else:
-        if b'..' in path_dst:
-            # remap, relative to project root
-
-            # paths
-            path_dst = os.path.join(blendfile_src_dir_fakeroot, path_dst)
-            path_dst = os.path.normpath(path_dst)
-            # if there are paths outside the root still...
-            # This means they are outside the project directory, We dont support this,
-            # so name accordingly
-            if b'..' in path_dst:
-                # SHOULD NEVER HAPPEN
-                path_dst = path_dst.replace(b'..', b'__nonproject__')
-            path_dst = b'_' + path_dst
-
-    # _dbg(b"FINAL A: " + path_dst)
-    path_dst_final = os.path.join(os.path.relpath(base_dir_src, fp_basedir), path_dst)
-    path_dst_final = os.path.normpath(path_dst_final)
-    # _dbg(b"FINAL B: " + path_dst_final)
-
-    return path_dst, path_dst_final
-
-
-def pack(
-        # store the blendfile relative to this directory, can be:
-        #    os.path.dirname(blendfile_src)
-        # but in some cases we wan't to use a path higher up.
-        # base_dir_src,
-        blendfile_src, blendfile_dst,
-        mode='ZIP',
-        # optionally pass in the temp dir
-        base_dir_dst_temp=None,
-        paths_re

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-extensions-cvs mailing list