Added exclusion filter to blendfile_pack:main()

Also improved CLI descriptions and added some assertions to help debuggin
stuff.
This commit is contained in:
2017-04-21 17:51:00 +02:00
parent a6c5400db2
commit eaa10175fe
2 changed files with 54 additions and 37 deletions

View File

@@ -47,11 +47,11 @@ def _dbg(text):
def _relpath_remap(
path_src: str,
base_dir_src: str,
fp_basedir: str,
blendfile_src_dir_fakeroot: str=None,
) -> (str, str):
path_src,
base_dir_src,
fp_basedir,
blendfile_src_dir_fakeroot=None,
):
if not os.path.isabs(path_src):
# Absolute win32 paths on a unix system
@@ -180,14 +180,19 @@ def pack(
else:
from bam.utils.system import colorize_dummy as colorize
assert isinstance(blendfile_src, bytes)
assert isinstance(blendfile_dst, bytes)
# in case this is directly from the command line or user-input
blendfile_src = os.path.normpath(os.path.abspath(blendfile_src))
blendfile_dst = os.path.normpath(os.path.abspath(blendfile_dst))
assert blendfile_src != blendfile_dst
# first check args are OK
# fakeroot _cant_ start with a separator, since we prepend chars to it.
assert((blendfile_src_dir_fakeroot is None) or
(not blendfile_src_dir_fakeroot.startswith(os.sep.encode('ascii'))))
if blendfile_src_dir_fakeroot is not None:
assert isinstance(blendfile_src_dir_fakeroot, bytes)
assert not blendfile_src_dir_fakeroot.startswith(os.sep.encode('ascii'))
path_temp_files = set()
path_copy_files = set()
@@ -212,6 +217,7 @@ def pack(
base_dir_dst = os.path.dirname(blendfile_dst)
# _dbg(blendfile_src)
# _dbg(blendfile_dst)
assert base_dir_src != base_dir_dst
if base_dir_dst_temp is None:
# Always try to pack using a unique folder name.
@@ -407,6 +413,7 @@ def pack(
# add to copy-list
# never copy libs (handled separately)
if not isinstance(fp, blendfile_path_walker.FPElem_block_path) or fp.userdata[0].code != b'LI':
assert path_src != path_dst
path_copy_files.add((path_src, path_dst))
for file_list in (
@@ -514,6 +521,7 @@ def pack(
for src, dst in path_copy_files:
assert(b'.blend' not in dst)
assert src != dst
# in rare cases a filepath could point to a directory
if (not os.path.exists(src)) or os.path.isdir(src):
@@ -589,14 +597,18 @@ def create_argparse():
"-i", "--input", dest="path_src", metavar='FILE', required=True,
help="Input path(s) or a wildcard to glob many files",
)
parser.add_argument(
"-e", "--exclude", dest="exclude", metavar='PATTERN', required=False,
help='Exclusion pattern, such as "*.abc;*.mov;*.mkv"')
parser.add_argument(
"-o", "--output", dest="path_dst", metavar='DIR', required=True,
help="Output file or a directory when multiple inputs are passed",
help="Output file (must be a .blend for --mode=FILE or a .zip when --mode=ZIP), "
"or a directory when multiple inputs are passed",
)
parser.add_argument(
"-m", "--mode", dest="mode", metavar='MODE', required=False,
choices=('FILE', 'ZIP'), default='ZIP',
help="Output file or a directory when multiple inputs are passed",
help="FILE copies the blend file(s) + dependencies to a directory, ZIP to an archive.",
)
parser.add_argument(
"-q", "--quiet", dest="use_quiet", action='store_true', required=False,
@@ -604,17 +616,40 @@ def create_argparse():
)
parser.add_argument(
"-t", "--temp", dest="temp_path", metavar='DIR', required=False,
help="Temporary directory to use",
help="Temporary directory to use. When not supplied, a unique directory is used.",
)
return parser
def main():
import sys
def exclusion_filter(exclude: str):
"""Converts a filter string "*.abc;*.def" to a function that can be passed to pack().
If 'exclude' is None or an empty string, returns None (which means "no filtering").
"""
if not exclude:
return None
import re
import fnmatch
# convert string into regex callback that operates on bytes
# "*.txt;*.png;*.rst" --> rb".*\.txt$|.*\.png$|.*\.rst$"
pattern = b'|'.join(fnmatch.translate(f).encode('utf-8')
for f in exclude.split(';')
if f)
compiled_pattern = re.compile(pattern, re.IGNORECASE)
def filename_filter(fname: bytes):
return not compiled_pattern.match(fname)
return filename_filter
def main():
parser = create_argparse()
args = parser.parse_args(sys.argv[1:])
args = parser.parse_args()
if args.use_quiet:
def report(msg):
@@ -625,12 +660,11 @@ def main():
sys.stdout.flush()
for msg in pack(
args.path_src.encode('utf-8'),
args.path_dst.encode('utf-8'),
args.path_src.encode('utf8'),
args.path_dst.encode('utf8'),
mode=args.mode,
base_dir_dst_temp=(
args.temp_path.encode('utf-8')
if args.temp_path else None),
base_dir_dst_temp=args.temp_path,
filename_filter=exclusion_filter(args.exclude),
):
report(msg)

View File

@@ -1357,24 +1357,7 @@ class bam_commands:
repository_base_path = repository_base_path.encode('utf-8')
# replace var with a pattern matching callback
if filename_filter:
# convert string into regex callback
# "*.txt;*.png;*.rst" --> r".*\.txt$|.*\.png$|.*\.rst$"
import re
import fnmatch
compiled_pattern = re.compile(
b'|'.join(fnmatch.translate(f).encode('utf-8')
for f in filename_filter.split(";") if f),
re.IGNORECASE,
)
def filename_filter(f):
return (not filename_filter.compiled_pattern.match(f))
filename_filter.compiled_pattern = compiled_pattern
del compiled_pattern
del re, fnmatch
filename_filter_cb = blendfile_pack.exclusion_filter(filename_filter)
for msg in blendfile_pack.pack(
path.encode('utf-8'),
@@ -1386,7 +1369,7 @@ class bam_commands:
report=report,
warn_remap_externals=warn_remap_externals,
use_variations=True,
filename_filter=filename_filter,
filename_filter=filename_filter_cb,
):
pass