Added exclusion filter to blendfile_pack:main()
Also improved CLI descriptions and added some assertions to help debuggin stuff.
This commit is contained in:
@@ -47,11 +47,11 @@ def _dbg(text):
|
|||||||
|
|
||||||
|
|
||||||
def _relpath_remap(
|
def _relpath_remap(
|
||||||
path_src: str,
|
path_src,
|
||||||
base_dir_src: str,
|
base_dir_src,
|
||||||
fp_basedir: str,
|
fp_basedir,
|
||||||
blendfile_src_dir_fakeroot: str=None,
|
blendfile_src_dir_fakeroot=None,
|
||||||
) -> (str, str):
|
):
|
||||||
|
|
||||||
if not os.path.isabs(path_src):
|
if not os.path.isabs(path_src):
|
||||||
# Absolute win32 paths on a unix system
|
# Absolute win32 paths on a unix system
|
||||||
@@ -180,14 +180,19 @@ def pack(
|
|||||||
else:
|
else:
|
||||||
from bam.utils.system import colorize_dummy as colorize
|
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
|
# in case this is directly from the command line or user-input
|
||||||
blendfile_src = os.path.normpath(os.path.abspath(blendfile_src))
|
blendfile_src = os.path.normpath(os.path.abspath(blendfile_src))
|
||||||
blendfile_dst = os.path.normpath(os.path.abspath(blendfile_dst))
|
blendfile_dst = os.path.normpath(os.path.abspath(blendfile_dst))
|
||||||
|
assert blendfile_src != blendfile_dst
|
||||||
|
|
||||||
# first check args are OK
|
# first check args are OK
|
||||||
# fakeroot _cant_ start with a separator, since we prepend chars to it.
|
# fakeroot _cant_ start with a separator, since we prepend chars to it.
|
||||||
assert((blendfile_src_dir_fakeroot is None) or
|
if blendfile_src_dir_fakeroot is not None:
|
||||||
(not blendfile_src_dir_fakeroot.startswith(os.sep.encode('ascii'))))
|
assert isinstance(blendfile_src_dir_fakeroot, bytes)
|
||||||
|
assert not blendfile_src_dir_fakeroot.startswith(os.sep.encode('ascii'))
|
||||||
|
|
||||||
path_temp_files = set()
|
path_temp_files = set()
|
||||||
path_copy_files = set()
|
path_copy_files = set()
|
||||||
@@ -212,6 +217,7 @@ def pack(
|
|||||||
base_dir_dst = os.path.dirname(blendfile_dst)
|
base_dir_dst = os.path.dirname(blendfile_dst)
|
||||||
# _dbg(blendfile_src)
|
# _dbg(blendfile_src)
|
||||||
# _dbg(blendfile_dst)
|
# _dbg(blendfile_dst)
|
||||||
|
assert base_dir_src != base_dir_dst
|
||||||
|
|
||||||
if base_dir_dst_temp is None:
|
if base_dir_dst_temp is None:
|
||||||
# Always try to pack using a unique folder name.
|
# Always try to pack using a unique folder name.
|
||||||
@@ -407,6 +413,7 @@ def pack(
|
|||||||
# add to copy-list
|
# add to copy-list
|
||||||
# never copy libs (handled separately)
|
# never copy libs (handled separately)
|
||||||
if not isinstance(fp, blendfile_path_walker.FPElem_block_path) or fp.userdata[0].code != b'LI':
|
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))
|
path_copy_files.add((path_src, path_dst))
|
||||||
|
|
||||||
for file_list in (
|
for file_list in (
|
||||||
@@ -514,6 +521,7 @@ def pack(
|
|||||||
|
|
||||||
for src, dst in path_copy_files:
|
for src, dst in path_copy_files:
|
||||||
assert(b'.blend' not in dst)
|
assert(b'.blend' not in dst)
|
||||||
|
assert src != dst
|
||||||
|
|
||||||
# in rare cases a filepath could point to a directory
|
# in rare cases a filepath could point to a directory
|
||||||
if (not os.path.exists(src)) or os.path.isdir(src):
|
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,
|
"-i", "--input", dest="path_src", metavar='FILE', required=True,
|
||||||
help="Input path(s) or a wildcard to glob many files",
|
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(
|
parser.add_argument(
|
||||||
"-o", "--output", dest="path_dst", metavar='DIR', required=True,
|
"-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(
|
parser.add_argument(
|
||||||
"-m", "--mode", dest="mode", metavar='MODE', required=False,
|
"-m", "--mode", dest="mode", metavar='MODE', required=False,
|
||||||
choices=('FILE', 'ZIP'), default='ZIP',
|
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(
|
parser.add_argument(
|
||||||
"-q", "--quiet", dest="use_quiet", action='store_true', required=False,
|
"-q", "--quiet", dest="use_quiet", action='store_true', required=False,
|
||||||
@@ -604,17 +616,40 @@ def create_argparse():
|
|||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-t", "--temp", dest="temp_path", metavar='DIR', required=False,
|
"-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
|
return parser
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def exclusion_filter(exclude: str):
|
||||||
import sys
|
"""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()
|
parser = create_argparse()
|
||||||
args = parser.parse_args(sys.argv[1:])
|
args = parser.parse_args()
|
||||||
|
|
||||||
if args.use_quiet:
|
if args.use_quiet:
|
||||||
def report(msg):
|
def report(msg):
|
||||||
@@ -625,12 +660,11 @@ def main():
|
|||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
for msg in pack(
|
for msg in pack(
|
||||||
args.path_src.encode('utf-8'),
|
args.path_src.encode('utf8'),
|
||||||
args.path_dst.encode('utf-8'),
|
args.path_dst.encode('utf8'),
|
||||||
mode=args.mode,
|
mode=args.mode,
|
||||||
base_dir_dst_temp=(
|
base_dir_dst_temp=args.temp_path,
|
||||||
args.temp_path.encode('utf-8')
|
filename_filter=exclusion_filter(args.exclude),
|
||||||
if args.temp_path else None),
|
|
||||||
):
|
):
|
||||||
report(msg)
|
report(msg)
|
||||||
|
|
||||||
|
21
bam/cli.py
21
bam/cli.py
@@ -1357,24 +1357,7 @@ class bam_commands:
|
|||||||
repository_base_path = repository_base_path.encode('utf-8')
|
repository_base_path = repository_base_path.encode('utf-8')
|
||||||
|
|
||||||
# replace var with a pattern matching callback
|
# replace var with a pattern matching callback
|
||||||
if filename_filter:
|
filename_filter_cb = blendfile_pack.exclusion_filter(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
|
|
||||||
|
|
||||||
for msg in blendfile_pack.pack(
|
for msg in blendfile_pack.pack(
|
||||||
path.encode('utf-8'),
|
path.encode('utf-8'),
|
||||||
@@ -1386,7 +1369,7 @@ class bam_commands:
|
|||||||
report=report,
|
report=report,
|
||||||
warn_remap_externals=warn_remap_externals,
|
warn_remap_externals=warn_remap_externals,
|
||||||
use_variations=True,
|
use_variations=True,
|
||||||
filename_filter=filename_filter,
|
filename_filter=filename_filter_cb,
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user