mirror of
https://github.com/blender/blender
synced 2026-09-29 04:37:17 +03:00
I noticed my recent files list was getting randomly cleared, and traced
it to running this test. Use wm.previews_clear instead.
Issue introduced in 216c095d5d.
Pull Request: https://projects.blender.org/blender/blender/pulls/157483
184 lines
5.8 KiB
Python
184 lines
5.8 KiB
Python
# SPDX-FileCopyrightText: 2026 Blender Authors
|
|
#
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
# Tests for `source/blender/python/intern/bpy_operator_function.cc`
|
|
# Python calling into the operator system (using a callable function like type).
|
|
#
|
|
# ./blender.bin --background --python tests/python/bl_operator_function_py_api.py -- --verbose
|
|
|
|
__all__ = (
|
|
"main",
|
|
)
|
|
|
|
import unittest
|
|
|
|
import bpy
|
|
|
|
|
|
class TestOperatorFunctionAccess(unittest.TestCase):
|
|
|
|
def test_access_operator(self):
|
|
op = bpy.ops.object.select_all
|
|
self.assertTrue(callable(op))
|
|
|
|
|
|
class TestOperatorCall(unittest.TestCase):
|
|
|
|
def test_call_previews_clear(self):
|
|
self.assertEqual(bpy.ops.wm.previews_clear(), {'FINISHED'})
|
|
|
|
|
|
class TestOperatorCallPositionalArgs(unittest.TestCase):
|
|
|
|
def test_exec_default(self):
|
|
self.assertEqual(bpy.ops.wm.previews_clear('EXEC_DEFAULT'), {'FINISHED'})
|
|
|
|
def test_invoke_default(self):
|
|
self.assertEqual(bpy.ops.wm.previews_clear('INVOKE_DEFAULT'), {'FINISHED'})
|
|
|
|
def test_undo_flag(self):
|
|
self.assertEqual(bpy.ops.wm.previews_clear(True), {'FINISHED'})
|
|
|
|
def test_undo_flag_false(self):
|
|
self.assertEqual(bpy.ops.wm.previews_clear(False), {'FINISHED'})
|
|
|
|
def test_undo_flag_int(self):
|
|
self.assertEqual(bpy.ops.wm.previews_clear(1), {'FINISHED'})
|
|
|
|
def test_undo_flag_int_zero(self):
|
|
self.assertEqual(bpy.ops.wm.previews_clear(0), {'FINISHED'})
|
|
|
|
def test_context_and_undo(self):
|
|
self.assertEqual(bpy.ops.wm.previews_clear('EXEC_DEFAULT', True), {'FINISHED'})
|
|
|
|
def test_context_and_undo_int(self):
|
|
self.assertEqual(bpy.ops.wm.previews_clear('EXEC_DEFAULT', 1), {'FINISHED'})
|
|
|
|
def test_negative_int(self):
|
|
self.assertEqual(bpy.ops.wm.previews_clear(-1), {'FINISHED'})
|
|
|
|
|
|
class TestOperatorCallPositionalArgsInvalid(unittest.TestCase):
|
|
|
|
def test_args_invalid_type(self):
|
|
for arg in (1.0, None, [], {}, (), set(), b'EXEC_DEFAULT'):
|
|
with self.assertRaises(ValueError):
|
|
bpy.ops.wm.previews_clear(arg)
|
|
|
|
def test_args_invalid_order(self):
|
|
for args in (
|
|
(True, 'EXEC_DEFAULT'),
|
|
(1, 'EXEC_DEFAULT'),
|
|
):
|
|
with self.assertRaises(ValueError):
|
|
bpy.ops.wm.previews_clear(*args)
|
|
|
|
def test_args_invalid_duplicates(self):
|
|
for args in (
|
|
(True, True),
|
|
(False, False),
|
|
(1, 1),
|
|
(1, True),
|
|
('EXEC_DEFAULT', 'EXEC_DEFAULT'),
|
|
('EXEC_DEFAULT', True, 'extra'),
|
|
(True, True, 'EXEC_DEFAULT', 'EXEC_DEFAULT'),
|
|
):
|
|
with self.assertRaises(ValueError):
|
|
bpy.ops.wm.previews_clear(*args)
|
|
|
|
|
|
class TestOperatorCallKeywordArgs(unittest.TestCase):
|
|
|
|
def test_enum_keyword(self):
|
|
self.assertEqual(bpy.ops.object.select_all(action='TOGGLE'), {'FINISHED'})
|
|
|
|
def test_keyword_with_context(self):
|
|
self.assertEqual(
|
|
bpy.ops.object.select_all('EXEC_DEFAULT', action='TOGGLE'), {'FINISHED'})
|
|
|
|
def test_keyword_with_context_and_undo(self):
|
|
self.assertEqual(
|
|
bpy.ops.object.select_all('EXEC_DEFAULT', True, action='TOGGLE'), {'FINISHED'})
|
|
|
|
def test_multiple_keywords(self):
|
|
self.assertEqual(
|
|
bpy.ops.mesh.primitive_cube_add(size=1.0, location=(0, 0, 0)), {'FINISHED'})
|
|
|
|
|
|
class TestOperatorCallKeywordArgsInvalid(unittest.TestCase):
|
|
|
|
def test_invalid_enum_value(self):
|
|
with self.assertRaises(TypeError):
|
|
bpy.ops.object.select_all(action='INVALID')
|
|
|
|
def test_wrong_type_for_enum(self):
|
|
with self.assertRaises(TypeError):
|
|
bpy.ops.object.select_all(action=123)
|
|
|
|
def test_wrong_type_for_float(self):
|
|
with self.assertRaises(TypeError):
|
|
bpy.ops.mesh.primitive_cube_add(size='big')
|
|
|
|
def test_wrong_type_for_bool(self):
|
|
with self.assertRaises(TypeError):
|
|
bpy.ops.mesh.primitive_cube_add(align='WORLD', calc_uvs='yes')
|
|
|
|
def test_none_for_enum(self):
|
|
with self.assertRaises(TypeError):
|
|
bpy.ops.object.select_all(action=None)
|
|
|
|
def test_none_for_float(self):
|
|
with self.assertRaises(TypeError):
|
|
bpy.ops.mesh.primitive_cube_add(size=None)
|
|
|
|
def test_list_for_float(self):
|
|
with self.assertRaises(TypeError):
|
|
bpy.ops.mesh.primitive_cube_add(size=[1.0])
|
|
|
|
def test_unknown_keyword(self):
|
|
with self.assertRaises(TypeError):
|
|
bpy.ops.object.select_all(nonexistent=True)
|
|
|
|
def test_multiple_unknown_keywords(self):
|
|
with self.assertRaises(TypeError):
|
|
bpy.ops.object.select_all(foo=1, bar=2)
|
|
|
|
def test_valid_and_unknown_keyword(self):
|
|
with self.assertRaises(TypeError):
|
|
bpy.ops.object.select_all(action='TOGGLE', nonexistent=True)
|
|
|
|
def test_empty_string_for_enum(self):
|
|
with self.assertRaises(TypeError):
|
|
bpy.ops.object.select_all(action='')
|
|
|
|
def test_non_string_keywords(self):
|
|
for key in (1, None, (1, 2)):
|
|
with self.assertRaises(TypeError):
|
|
bpy.ops.object.select_all(**{key: 'TOGGLE'})
|
|
|
|
|
|
class TestOperatorCallInvalid(unittest.TestCase):
|
|
|
|
def test_invalid_context_string(self):
|
|
with self.assertRaises(TypeError):
|
|
bpy.ops.wm.previews_clear('INVALID_CONTEXT')
|
|
|
|
def test_invalid_keyword_argument(self):
|
|
with self.assertRaises(TypeError):
|
|
bpy.ops.wm.previews_clear(nonexistent_prop=True)
|
|
|
|
def test_poll_failure(self):
|
|
# Edit-mode operator cannot run without an active mesh in edit-mode.
|
|
with self.assertRaises(RuntimeError):
|
|
bpy.ops.mesh.subdivide()
|
|
|
|
|
|
def main():
|
|
import sys
|
|
sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else [])
|
|
unittest.main()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|