Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save unwave/55fa7d4c551d93840db920506bd2666a to your computer and use it in GitHub Desktop.
Save unwave/55fa7d4c551d93840db920506bd2666a to your computer and use it in GitHub Desktop.
# test blender socket custom properties
def get_script(func, *args, **kwargs):
import textwrap
import inspect
import json
return '\n'.join([
textwrap.dedent(inspect.getsource(func)),
"import json",
f"{func.__name__}(*json.loads(r'{json.dumps(args)}'), **json.loads(r'{json.dumps(kwargs)}'))"
])
def ensure_site_packages(packages: list, directory: str):
"""
`packages`: list of tuples (<import name>, <pip name>)
`directory`: a folder for site packages, will be created if does not exist and added to `sys.path`
"""
if not packages:
return
import bpy
import os
import sys
import importlib
import importlib.util
os.makedirs(directory, exist_ok = True)
if not directory in sys.path:
sys.path.append(directory)
modules_to_install = [module[1] for module in packages if not importlib.util.find_spec(module[0])]
if not modules_to_install:
return
if modules_to_install:
result = input(f'Install {modules_to_install} to: {directory}? Y/N:')
if not result.lower() == 'y':
quit()
if bpy.app.version < (2,91,0):
python_binary = bpy.app.binary_path_python
else:
python_binary = sys.executable
import subprocess
subprocess.run([python_binary, '-m', 'ensurepip'], check=True)
subprocess.run([python_binary, '-m', 'pip', 'install', *modules_to_install, "--target", directory], check=True)
importlib.invalidate_caches()
def is_in_blender():
try:
import bpy
return bool(bpy.app.version) and bool(bpy.app.binary_path)
except:
return False
def get_mat():
import bpy
material = bpy.data.materials.new('test_mat')
material.use_nodes = True
material.use_fake_user = True
material.node_tree.nodes.clear()
return material
def pytest_namespace():
return {
'mat_name': '',
'blend_file': '',
'rand_value_1': None,
'rand_value_2': None
}
def test_create():
import pytest
import bpy
import os
import random
material = get_mat()
pytest.mat_name = material.name
nodes = material.node_tree.nodes
math = nodes.new('ShaderNodeMath')
math2 = nodes.new('ShaderNodeMath')
input_0 = math.inputs[0]
input_1 = math2.inputs[1]
input_0['my_default_value'] = int(random.random() * 1000)
input_1['my_default_value'] = int(random.random() * 1000)
math2.inputs[1]['will_be_deleted'] = 'some_value'
pytest.rand_value_1 = input_0['my_default_value']
pytest.rand_value_2 = input_1['my_default_value']
pytest.blend_file = os.path.join(bpy.app.tempdir, f'test_blend{random.random()}.blend')
bpy.ops.wm.save_mainfile(filepath=pytest.blend_file)
def test_check():
import pytest
import bpy
if bpy.app.version > (2,90,0):
bpy.ops.wm.read_homefile(load_ui=True, use_factory_startup=True, use_empty = True)
else:
bpy.ops.wm.read_homefile(load_ui=True, use_empty = True)
bpy.ops.wm.open_mainfile(filepath=pytest.blend_file)
material = bpy.data.materials[pytest.mat_name]
nodes = material.node_tree.nodes
print(dict(nodes[0].inputs[0].items()))
assert nodes[0].inputs[0]['my_default_value'] == pytest.rand_value_1
print(dict(nodes[1].inputs[1].items()))
assert nodes[1].inputs[1]['my_default_value'] == pytest.rand_value_2
try:
nodes[1].inputs[1].id_properties_clear()
except AttributeError:
assert nodes[1].inputs[1]['will_be_deleted']
del nodes[1].inputs[1]['will_be_deleted']
finally:
with pytest.raises(KeyError):
nodes[1].inputs[1]['will_be_deleted']
def test_separate_instance():
import subprocess
import pytest
import bpy
def run(value):
import bpy
assert bpy.data.materials['test_mat'].node_tree.nodes[0].inputs[0]['my_default_value'] == value
subprocess.run([bpy.app.binary_path, '--python-exit-code', '1', '-b', '-noaudio', '--factory-startup', pytest.blend_file, '--python-expr', get_script(run, pytest.rand_value_1)], check=True)
if __name__ == "__main__" and is_in_blender():
import site
ensure_site_packages([("pytest", "pytest")], directory = site.getusersitepackages())
import pytest
raise SystemExit(pytest.main([
'-svv',
__file__
]))
blenders = [
r'blender',
r'C:\blender\blender-3.1.2-windows-x64\blender.exe',
r'C:\blender\blender-3.6.0-alpha+main.e078419c9c12-windows.amd64-release\blender.exe',
r'C:\Program Files (x86)\Steam\steamapps\common\Blender\blender.exe',
r'D:\games\SteamLibrary\steamapps\common\blender_293\blender.exe',
r'D:\games\SteamLibrary\steamapps\common\blender-2.83.13-windows64\blender.exe',
r'D:\source\software\blender\blender-2.82-windows64\blender.exe',
r'D:\games\SteamLibrary\steamapps\common\blender-2.79.0-git.e045fe53f1b0-windows64\blender.exe',
]
if __name__ == '__main__' and not is_in_blender():
import subprocess
import os
for blender in blenders:
print('\n')
print('#' * os.get_terminal_size()[0])
# print(subprocess.check_output([blender, '--version']).splitlines()[0].decode())
subprocess.run([blender, '--python-exit-code', '1', '-b', '-noaudio', '--factory-startup', '--python', __file__])
if os.name == 'nt':
os.system('pause')
else:
input('Press Enter to exit...')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment