Page MenuHome

Identifier resulted from prop_search is prefixed by three spaces.
Open, ConfirmedPublic

Description

Short description of error

The identifier resulted from prop_search is prefixed by three spaces. For instance, if an object is named Cube and it was chosen using prop_search, the resulted identifier will be Cube with three spaces before the object's name.

Exact steps for others to reproduce the error

Execute the following script and select an object:

import bpy
from bpy.props import StringProperty

def printObjectName(self, context):
    print(repr(context.scene.objectName))

class BugPanel(bpy.types.Panel):
    bl_label = "Bug Panel"
    bl_idname = "bug"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "object"

    def draw(self, context):
        self.layout.prop_search(context.scene, "objectName", context.scene, "objects")

bpy.types.Scene.objectName = StringProperty(update = printObjectName)
bpy.utils.register_class(BugPanel)

Looking at the terminal or the info area, you will see that objectName is actually the name of the chosen object prefixed by three spaces.

Details

Type
Bug

Event Timeline

It sounds like a bug to me, can't think of a reason why it should be like that.

I looked into the code and it seems like these three letters are used to differentiate e.g. linked objects.

Eeeeeh… well, thing is, for UI display, we use those three-chars prefixed names (having some info like linked, orphaned, etc.). It will also append the library name in case of linked datablock. This ensures fully unique ID name (identifier, inside of a given ID type) across whole .blend file.

Also note that in 2.8, you can use that 'decorated' unique ID identifier directly to retrieve the ID, so once you have selected an object in your searchbutton, bpy.data.objects[C.scene.objectName] will retrieve expected object.

Keeping those two-letters keycode in our ID names in UI might be a topic to discuss for UI team, I think they are still nice to have though, but we could also get rid of them.

But handling two different set of data in search_prop code would require a serious rewrite of the whole search code (I considered it few months ago when I fixed the 'lib IDs with same name as local ones are not selectable' issue, but decided it was much more simple to make the bpy.data.xxx[] syntax to also accept extended names instead ;) ).

So IMHO there is no bug here, that's how search_prop & ID work together currently. ID should be stored in Pointer properties anyway, not string ones, ideally.

Well, this little trick does not make id names really unique, right? When I have two local objects named Cube and L Cube [untitled.blend] and one linked object called Cube (linked from a file called untitled.blend), then I can't access the linked object object from bpy.data.objects[...].

So while it might make the name collisions less likely, it does not actually solve the problem.
I'm fine with .prop_search always yielding those extra letters (that should really be mentioned in the release notes), however I don't think bpy.data.objects[...] should accept this format and try to be smart. This would only work if you'd always have to put the three spaces in for local objects. And I think that makes the api much worse.
Something like bpy.data.objects.get_from_lib(extended_name) or bpy.data.objects[(name, lib)] makes more sense.

If you are crazy enough to name your objects that way, there is no miracle indeed. That’s why I said that ID should be stored in Pointer prop, not string one, unless absolutely not possible to do otherwise.

But if you are interested in diving into the search_prop & friends maze to avoid that behavior, be my guest. For now I think we have something that works well and easily in all decent cases. If user wants to start naming their object L Cube [untitled.blend], that’s their issue. Just use Pointer prop to store IDs then.

Ok, I think that .prop_search uses the extended names is fine. (If it is documented somewhere what all the letters mean exactly. I have not found any docs for that yet.)

I'm mostly unsure if bpy.data.xxx[...] should allow that input directly as it clearly does not make name collisions impossible.

Also, is there some way to get the extended name from an object (without having to build it manually somehow)?

Making name collision impossible with a single string is close to impossible (guess since ID names have fixed max length, we could force lib part beyond the 67th char to get that result, but would not be very user-friendly display then).

But I do not understand why you are splitting hair here, name collision is impossible in any sane normal naming layout. Again, if some crazy user starts naming its local datablocks to mimic linked ones, so be it. We are not responsible for that, and we can expect a reasonable amount of decent common sense. Otherwise, we can trash blender, since we'll never have manpower to tackle all possible crazy corner cases.

And yes of course there is, https://docs.blender.org/api/blender2.8/bpy.types.ID.html#bpy.types.ID.name_full (without the three-letters prefix, which is dedicated to UI code).

And I do not think prop_search storing extended name is fine, it's just way too complicated to change this to store actual full ID name, so not worth the effort imho.

ok.

Maybe the description of ID.name should be changed.
So we have three types of names in the api now?

  • object name
  • object name + library part
  • prefix + object name + library part

For the records, this also causes T58917 to happen. I will see there if I can change the stored data to pointer (don't recall why I used strings in the first place).