[Bf-committers] ops functions, parameters, and returns

Campbell Barton ideasman42 at gmail.com
Tue Mar 23 08:36:09 CET 2010

Hi Charles,
Operator access from python is ugly at the moment, its like that room
you didn't get time to tidy up before the guests (read users) arrive
Since we didn't keep the door shut you can see the ugly internals.
At the moment I spend more time on basic problems (except on weekends)

replies to some of your questions inline.

On Sun, Mar 21, 2010 at 6:34 PM, Charles Wardlaw
<cwardlaw at marchentertainment.com> wrote:
> Hi again Campbell,
>> Operators are tools and not api functions, the idea is that operators
>> manipulate the context so python can be used to create macro's
>> What an operator would return isnt always clear, for instance if you
>> link in objects, would it contain a list of every object, scene and
>> text blocked linked??
> Perhaps.  Or if you link in a scene, then the scene would be returned by itself and would be traversable like bpy.data.scenes.
> I don't know that linking is a good example-- linking in / appending objects of different types should, I think, have different returns.  Linking in a group for character rig linking, for instance, should return a list like the following:
> [ 'FINISHED', group, armature1, armature2, ... armatureN, mesh1, mesh2, ... meshN ]
> That way scripts could go in and add proxies automatically to all armature objects that have been linked in.
> I think that returns should be opened up to discussion, to see how people would expect things to work.  Linking aside, I would like to see any add() function return a handle for the added data. So that something like:
> ob = bpy.object.addObject(name="Foo")
> ob.data = bpy.armature.addArmature(name="Bar")
> would work.  I'd get rid of all the 'FINISHED' returns since it's just as easy to check for a NoneType return, or an empty tuple.

This makes sense if we deal with operators as if their main purpose is
for python API access, A while ago we did talk bout ways operators
might receive and return 'selection groups', Id still like to allow
something like this but dont have time at the moment.

>> however in some cases its really obvious that you would want to run an
>> operator and get a return value, in these cases we should probably
>> make RNA function calls for these operators (internally they can use
>> the same C functions).
>> There are also quite a few cases where the operators should be removed
>> and only have API calls only. Things like "Move Modifier Up" IMHO are
>> not useful as operators.
>> But then we need to see how rna function calls can be done from the UI :S.
> Heh that's a question beyond me. :)  Although maybe it'd be nice to provide a function that registers a new operator based on a function and some arguments -- something similar to how the partial() stuff works in Python.
> The main thing is to make the API easy and intuitive for real coders, but also simple enough to understand for more casual users so that they can copy and paste from the script log to make their macros.
> At the moment I can copy and paste from the script log, but nothing in the commands there show how to rename objects or how to get at data.  Something as simple as modifying this call:
> bpy.ops.mesh.primitive_cube_add(view_align=False, enter_editmode=False, location=(-0.586031, -0.0568311, 7.21605), rotation=(0, 0, 0), layer=(False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False))
> to something more readable, stripping out default value passings:
> bpy.ops.mesh.primitive_cube_add(name="MyMesh", view_align=False, enter_editmode=False, location=(-0.586031, -0.0568311, 7.21605))
> would make life easier on casual scripters.  Now they know exactly how to change the name just by looking at the code, and they don't get overwhelmed looking at a really long list of things that are irrelevant. Incidentally if a location is passed, operators should bypass the 3D cursor. Or perhaps the functions should have a standard way of specifying at-cursor placements:
> bpy.ops.mesh.primitive_cube_add(location=(-0.586031, -0.0568311, 7.21605)) # ignore the cursor
> bpy.ops.mesh.primitive_cube_add(placement ='CURSOR') # place at cursor, ignore location kwarg
> In this case the default could be placement='WORLD'.  Then when commands show in the script log, users would see that the location type is being modified since the UI always places things at the cursor:
> bpy.ops.mesh.primitive_cube_add(name="MyMesh", view_align=False, enter_editmode=False, placement='CURSOR')
> Sure, you want users to read the manual and learn how to search for the functions they want, but there are users out there who will surprise you with what they can do with simple copy and pastes.

So far operators have been created from a user standpoint, so you get
odd results when converting an operator into a python function call.
Agree with some of your suggestions above however not all.

Operators are a way for python to access user tools, not just a python
api for all blender functionality.
So why should you be able to give the name of a new object? (as an
example), you dont get an option to enter a name as a user so why
should python?

Python just has to do what the user would do and rename after
 bpy.context.object.name = "MyMesh"

Not saying a name argument is bad per se, just that it doesnt always
make sense to add arguments when the data api can also modify these
values after.

>> We could try to make operators behave more like API functions but this
>> is not a small task and not what operators were originally designed to
>> do. so I think its out of the scope of 2.5 tool refactor.
> And maybe that's not the way to go.  I mean, it's easy enough to have functions with different kinds of returns, but I understand that it would go against the original design.
> At the same time, there could be easier methods for common tasks.  What those functions need to be are anyone's guess at the moment; I'll keep notes as I go, as should all python coders working with the Alphas.
>> Different developers wrote operators, mostly to get blender working
>> again and not having read how all other operators work. When you try
>> use operators from python you end up finding many problems like this.
> Ahh okay, no worries.  Moving forwards it would be nice to make names agree with each other, too.  Things like bpy.ops.mesh.primitive_circle_add bpy.ops.armature.bone_primitive_add should match.  (Although I think that the names should be shortened to addCircle and addBone respectively.)  On a personal note with regards to naming, it'd be *awesome* if the underscores were thrown out for camelCase.

Not going to get into an argument over this one, wasn't my decision
but Id say we'll stick to underscores.

>> for data creation and removal though we accept that operators are not
>> ideal and there are existing functions for this
>> # Example
>> arm = bpy.data.armatures.new("MyArmature")
>> obj = bpy.data.objects.new("MyObject", arm)
>> scene = bpy.context.scene
>> scene.objects.link(obj)
> Ahh cool, thanks for that.
> One last question: is there any particular reason why at this point objects require edit mode on the script side?  I know there's an update that's triggered on change from edit to object modes, but to me it seems like extra steps (not unlike how you have to leave edit mode to apply a modifier -- if it's smart enough to tell you that, it should be smart enough to toggle edit mode for you ^_^).

Id need to see the script, it could be a bug, badly written operator,
or you might run an operator that requires editmode. AFAIK automatic
mode switching isn't planed.

> ~ C
> PS: Thanks for fixing the help() function.
> _______________________________________________
> Bf-committers mailing list
> Bf-committers at blender.org
> http://lists.blender.org/mailman/listinfo/bf-committers

- Campbell

More information about the Bf-committers mailing list