Blender Crawl: Improvements based on User Feedback #53

Merged
Nick Alberelli merged 11 commits from fix/blender-crawl-improvements into main 2023-05-22 16:50:42 +02:00
5 changed files with 77 additions and 38 deletions

View File

@ -1,4 +1,4 @@
# blender_crawl
# Blender Crawl
`blender_crawl` is a command line tools to crawl directories for .blend files and execute a provied script.
## Table of Contents
- [Prerequisite](#prerequisite)
@ -10,32 +10,39 @@ In order to use this tool you need:
- Python 3.5+
## Run without Installation
This folder contains a command line tool that doesn't require installation to use properly. This tool doesn't require installation to be run. To run `blender-crawl` without installation follow the steps below.
1. Clone this repository with `git clone https://projects.blender.org/studio/blender-studio-pipeline.git`
2. Run `cd blender-studio-pipeline/scripts/blender-crawl` to enter directory
3. Run program with `python blender_crawl /my-folder/`
## Installation
Download or clone this repository.
This repository is a command line tool that can be installed with the python packaging manager.
## Installation (OPTIONAL)
Download or clone this repository. This repository is a command line tool that can be installed with the python packaging manager. Installation is an optional step only intended for advanced users.
This script does the following (follow this if you want to do this manually or on another platform):
Steps 3 and 5 are specific to linux, similar steps to gain root/administration privileges are avaliable to [Windows](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/jj717276(v=ws.11)) and [Mac](https://support.apple.com/en-ca/guide/terminal/apd5b0b6259-a7d4-4435-947d-0dff528912ba/mac) users.
1. Clone this repository with `git clone https://projects.blender.org/studio/blender-studio-pipeline.git`
2. Run `cd blender-studio-pipeline/scripts/blender-crawl` to enter directory
3. Install with `python setup.py install`
4. Run with `blender_crawl /my-folder/`
5. Get help with `blender_crawl -h`
3. Gain root access with `su` or equivalent command to grant permission to modify the system.
4. Install with `pip install .`
5. Type `exit` to log out of root user or equivalent command.
5. Run with `blender_crawl /my-folder/`
6. Get help with `blender_crawl -h`
## How to get started
Run directly out of repo folder or follow above installation instructions. Give `blender_crawl` a path to a .blend file or a folder as first argument, The detected blend files will be opened in the background, the python script will be executed, and the file closes. If blender is not installed at the default location of your computer, you need to provide a blender executable using the --exec flag.
If a script is provided, `blender_crawl` will automatically save after execution of the script, without saving any backups aka [save versions](https://docs.blender.org/manual/en/latest/editors/preferences/save_load.html#:~:text=of%20using%20characters.-,Save%20Versions,-Number%20of%20versions). If you already have saving logic in your provided script, skip this step using the "--nosave" flag.
| Command | Description |
| ----------- | ----------- |
| --script| Path to blender python script(s) to execute inside .blend files during crawl.|
| -n, --nosave|Don't save .blend after script execution.|
| -r, --recursive| If provided in combination with a folder path will perform recursive crawl|
| -f --filter| Provide a string to filter the found .blend files|
| -a, --ask| If provided there will be no confirmation prompt before running script on .blend files.|
| -p, --purge| Run 'built-in function to purge data-blocks from all .blend files found in crawl.'.|
| -a, --ask| If provided there will be a prompt for confirmation before running script on .blend files.|
| -p, --purge| Run 'built-in function to purge data-blocks from all .blend files found in crawl, and saves them.|
| --exec| If provided user must provide blender executable path, OS default blender will not be used if found.|
| -h, --help| show the above help message and exit|
@ -50,5 +57,6 @@ Run directly out of repo folder or follow above installation instructions. Give
|Run default 'Purge' script on .blends in Current Directory |`blender_crawl /my-folder/ --purge`|
|Run custom script on all .blends in Current Directory |`blender_crawl /my-folder/ --script /my-directory/my-script.py`|
|Ask/Prompt before script execution|`blender_crawl /my-folder/ --script /my-directory/my-script.py --ask`|
|Run script on .blends without saving |`blender_crawl /my-folder/ --script /my-directory/my-script.py --nosave` |
|Run with a custom blender executable|`blender_crawl /my-folder/ --exec /path-to-blender-executable/blender`|

View File

@ -27,12 +27,14 @@ import argparse
import re
from pathlib import Path
from typing import List
import tempfile
import uuid
# Command line arguments.
parser = argparse.ArgumentParser()
parser.add_argument(
"path",
help="Path to a file(s) or folder(s) on which to perform crawl",
help="Path to a file(s) or folder(s) on which to perform crawl.",
nargs='+'
)
@ -46,33 +48,39 @@ parser.add_argument(
parser.add_argument(
"-s",
"--script",
help="Path to blender python script(s) to execute inside .blend files during crawl. Execution is skipped if no script is provided",
help="Path to blender python script(s) to execute inside .blend files during crawl. Execution is skipped if no script is provided.",
nargs='+',
)
parser.add_argument(
"-n",
"--nosave",
help="Don't save .blend after script execution.",
action="store_true",
)
parser.add_argument(
"-r",
"--recursive",
help="If -r is provided in combination with a folder path will perform recursive crawl",
help="If -r is provided in combination with a folder path will perform recursive crawl.",
action="store_true",
)
parser.add_argument(
"-f",
"--filter",
help="Provide a string to filter the found .blend files",
help="Provide a string to filter the found .blend files.",
)
parser.add_argument(
"-a",
"--ask",
help="If --ask is provided there will be no confirmation prompt before running script on .blend files.",
help="If --ask is provided there will be a prompt for confirmation before running script on .blend files.",
action="store_true",
)
parser.add_argument(
"-p",
"--purge",
help="Run 'built-in function to purge data-blocks from all .blend files found in crawl.'.",
help="Run 'built-in function to purge data-blocks from all .blend files found in crawl, and saves them.",
action="store_true",
)
@ -120,7 +128,7 @@ def is_filepath_blend(path: Path) -> None:
cancel_program(f"Not a blend file: {path.suffix}")
def check_file_exists(file_path_str: str, error_msg: str):
def check_file_exists(file_path_str: str, error_msg: str) -> Path:
if file_path_str is None:
return
file_path = Path(file_path_str).absolute()
@ -129,22 +137,39 @@ def check_file_exists(file_path_str: str, error_msg: str):
else:
cancel_program(error_msg)
def script_append_save(script: Path, skip_save:bool):
if skip_save:
return script
save_script = get_default_script("save.py", True)
# Reading data from file1
with open(script) as script_file:
script_data = script_file.read()
# Reading data from file2
with open(save_script) as save_file:
save_data = save_file.read()
script_data += "\n"
script_data += save_data
temp_dir = Path(tempfile.TemporaryDirectory().name).parent
new_temp_file = Path.joinpath(Path(temp_dir), f"blender_crawl_{uuid.uuid4()}.py")
with open(new_temp_file, "w") as new_file:
new_file.write(script_data)
return new_temp_file
def get_purge_path(purge: bool):
def get_default_script(file_name:str, purge: bool):
# Cancel function if user has not supplied purge arg
if not purge:
return
scripts_directory = Path((os.path.dirname(__file__))).joinpath("default_scripts/")
purge_script = os.path.join(scripts_directory.resolve(), "purge.py")
purge_script = os.path.join(scripts_directory.resolve(), file_name)
return check_file_exists(str(purge_script), "Default scripts location may be invalid")
def main() -> int:
import sys
"""Crawl blender files in a directory and run a provided scripts"""
# Parse arguments.
args = parser.parse_args()
purge_path = get_purge_path(args.purge)
purge_path = get_default_script("purge.py", args.purge)
recursive = args.recursive
exec = args.exec
regex = args.filter
@ -154,15 +179,15 @@ def main() -> int:
scripts = []
if script_input:
for script in script_input:
script_name = check_file_exists(
script_path = check_file_exists(
script,
"No --script was not provided as argument, printed found .blend files, exiting program.",
)
scripts.append(script_name)
scripts.append(script_append_save(script_path, args.nosave))
# Purge is optional so it can be none
if purge_path is not None:
scripts.append(purge_path)
scripts.append(script_append_save(purge_path, args.nosave))
if not exec:
blender_exec = find_executable()
@ -227,7 +252,6 @@ def main() -> int:
)
sys.exit(0)
# crawl each file two times.
for blend_file in files:
for script in scripts:
cmd_list = (

View File

@ -20,18 +20,5 @@
# (c) 2021, Blender Foundation
import bpy
# Setup prefs.
bpy.context.preferences.filepaths.save_version = 0 #TODO Figure out why this is here
# Purge.
print("Starting Recursive Purge")
bpy.ops.outliner.orphans_purge(do_local_ids=True, do_linked_ids=True, do_recursive=True)
# Save.
bpy.ops.wm.save_mainfile()
print("Saved file: %s", bpy.data.filepath)
# Quit.
print("Closing File")
bpy.ops.wm.quit_blender()

View File

@ -0,0 +1,20 @@
import bpy
import contextlib
@contextlib.contextmanager
def override_save_version():
"""Overrides the save version settings"""
save_version = bpy.context.preferences.filepaths.save_version
try:
bpy.context.preferences.filepaths.save_version = 0
yield
finally:
bpy.context.preferences.filepaths.save_version = save_version
with override_save_version():
bpy.ops.wm.save_mainfile()
print(f"Saved file: '{bpy.data.filepath}'")
bpy.ops.wm.quit_blender()

View File

@ -27,7 +27,7 @@ setup(
keywords="blender_crawl",
name="blender_crawl",
packages=["blender_crawl", "blender_crawl.default_scripts",],
version="0.1.0",
version="0.1.1",
entry_points={"console_scripts": ["blender_crawl = blender_crawl.__main__:main"]},
package_data={'blender_crawl.default_scripts': ['*']}, #TODO Verify this is working correctly after install
)