<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class="">From the perspective of someone using the Python API to replicate interactions with the 3D viewport, that’s <i class="">VERY</i> confusing because it is extremely un-Pythonic and does not match the conceptual model of objects being either selected or unselected, visible not not visible, etc. Explicit getters and setters are normal in C++, but goes against the normal Python practice of avoiding getter and setter functions wherever possible in favor of overriding the assignment operator and implementing any getter/setter logic there. <font face="Courier New" class="">`Object.select_get()`</font> and <font face="Courier New" class="">`Object.select_set()`</font> perform <i class="">exactly the same operation</i> and have<i class=""> exactly the same result</i> as the builtin python special methods<font face="Courier New" class=""> __getattr__</font> and <font face="Courier New" class="">__setattr__</font>. I think this is a great example of “practicality beats purity”.</div><div class=""><br class=""></div><div class="">If I were writing a pure-python wrapper of Object, it would look something like this:</div><div class=""><br class=""></div><div class=""><font face="Courier New" class="">--- </font></div><div class=""><span style="font-family: "Courier New";" class="">class ObjectBase(bpy_struct):</span></div><div class=""><font face="Courier New" class="">    @property</font></div><div class=""><font face="Courier New" class="">    def select(self):</font></div><div class=""><font face="Courier New" class="">        # Code for select_get here</font></div><div class=""><font face="Courier New" class=""><br class=""></font></div><div class=""><font face="Courier New" class="">    @select.setter</font></div><div class=""><font face="Courier New" class="">    def select_setter(self, value):</font></div><div class=""><font face="Courier New" class="">        if isinstance(value, bool):</font></div><div class=""><font face="Courier New" class="">            # Code for select_set(value) here</font></div><div class=""><font face="Courier New" class="">        else:</font></div><div class=""><font face="Courier New" class="">            raise TypeError(“Expected a boolean”)</font></div><div class=""><font face="Courier New" class=""><br class=""></font></div><div class=""><div class=""><font face="Courier New" class="">class Object(bpy_struct):</font></div><div class=""><font face="Courier New" class="">    def __init__(self):</font></div><div class=""><font face="Courier New" class="">        self.base = ObjectBase()</font></div><div class=""><font face="Courier New" class=""><br class=""></font></div><div class=""><font face="Courier New" class="">    @property</font></div><div class=""><font face="Courier New" class="">    def select(self):</font></div><div class=""><font face="Courier New" class="">        return self.base.select</font></div><div class=""><font face="Courier New" class=""><br class=""></font></div><div class=""><font face="Courier New" class="">    @selected.setter</font></div><div class=""><font face="Courier New" class="">    def selected_setter(self, value):</font></div><div class=""><font face="Courier New" class="">        self.base.select = value</font></div></div><div class=""><font face="Courier New" class="">--- </font></div><div class=""><font face="Courier New" class=""><br class=""></font></div><div class="">This has several advantages:</div><div class=""><ul class="MailOutline"><li class="">It follows the conceptual model of objects being either selected or not, just like in the 3D viewport (very important for newcomers to Blender python scripting)</li><li class="">It does not introduce a breaking change in the Python API</li><li class="">It follows standard Python conventions</li><li class="">It keeps the API clean and simple, while allowing access to the base for more explicit control over selection state. </li></ul></div><div class=""><br class=""></div><div class="">One tweak that would make this even better (at the cost of slight API breakage) would be to rename “select” to “selected”. A weak adjective is a better description of what is being altered, and would be consistent with other parts of the API such as <font face="Courier New" class="">bpy.context.selected_objects</font>. </div><div class=""><br class=""></div><div class="">If you want to make it explicit that selection is a property of the base and not the object, you could remove the alias from Object and the context and always require it to be on the base, as Bassam suggested, in which case selection would be set with <font face="Courier New" class="">Object.base.selected = True</font>.</div><div class=""><br class=""><div class=""><div class=""><div class=""><div class=""><div class=""><div class=""><div class=""><div class=""><div class=""><div class=""><div class=""><div><blockquote type="cite" class=""><div class="">On Nov 12, 2018, at 7:11 AM, Bassam Kurdali <<a href="mailto:bassam@urchn.org" class="">bassam@urchn.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">Would it be more communicative (though more wordy) to call the function base_select() since it's not really a typical getter/setter (since the selection is on the base?</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">Either:</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">ob.base_select_get() and ob.base_select_set()</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">Or:</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">on.base_select() where all arguments are optional and calling with select=None or no argument just returns the current selection state while passing a True or False also sets it?</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">Cheers,</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">Bassam</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><div class="gmail_quote" style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;">On November 11, 2018 10:15:55 PM EST, Campbell Barton <<a href="mailto:ideasman42@gmail.com" class="">ideasman42@gmail.com</a>> wrote:<blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); padding-left: 1ex;"><pre class="k9mail"><a href="http://object.select/" class="">Object.select</a> is not really correct, since the selection state isn't<br class="">stored in the object.<br class=""><br class="">If we match Blender's internal state selection would look like this:<br class=""><br class="">----<br class="">ob_base = view_layer.base_find(ob)<br class="">if ob_base is not None:<br class="">    ob_<a href="http://base.select/" class="">base.select</a> = select<br class="">----<br class=""><br class="">In practice this is inconvenient, although I think hiding this<br class="">relationship entirely is also a problem.<br class=""><br class="">In recent 2.8 builds you can optionally pass in a view layer which<br class="">overrides the current active view layer, eg:<br class=""><br class="">    ob.select_set(True, view_layer)<br class=""><br class="">On Tue, Nov 6, 2018 at 7:02 AM Benjamin Humpherys<br class=""><<a href="mailto:benjamin.humpherys@gmail.com" class="">benjamin.humpherys@gmail.com</a>> wrote:<br class=""><blockquote class="gmail_quote" style="margin: 0pt 0pt 1ex 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(114, 159, 207); padding-left: 1ex;"><br class=""> It makes sense that selection and visibility are not Object properties, but that’s an implementation detail that I don’t believe should to be visible in the Python API. What I’m asking is that the appropriate getter and setter functions be called through the standard python property access methods. I’m not an expert on the Python C API, but shouldn’t it be possible to use `PyGetSetDef` to redirect property access to call the new getter and setter methods, without having to expose this change to Python code? For example: <a href="https://llllllllll.github.io/c-extension-tutorial/member-vs-getset.html" class="">https://llllllllll.github.io/c-extension-tutorial/member-vs-getset.html</a><br class=""><br class=""> On Nov 5, 2018, at 12:15 PM, Bastien Montagne <<a href="mailto:montagne29@wanadoo.fr" class="">montagne29@wanadoo.fr</a>> wrote:<br class=""><br class=""> Hi Benjamin,<br class=""><br class=""> TL;DR: We did that in 2.7x, it’s not possible anymore in 2.8x (not without **huge** changes in a large part of RNA, and adding significant complication to the API).<br class=""><br class=""> Technical explanation:<br class=""><br class=""> This decision was taken because selection status **is not an Object data**, not at all. It is stored in the object 'instantiation' data (called Base, and not exposed to Python) used to 'link' an object to a ViewLayer. Hence it is context-dependent info, which cannot be retrieved through our RNA property system.<br class=""><br class=""> Ideally, there should be no access at all to that status in RNA, at least no setter, it should be something let to operators, or alternatively, we’d have to expose the whole Base concept to python. But that would add some noise and confusion to something already rather complicated (whole viewlayer/collection/object system).<br class=""><br class=""> We have other similar accessors in Object API, like `visible_get()`, which follow the same principle (and do not have any setter).<br class=""><br class=""> Note that pure-python things like @property are totally irrelevant here, this is using the semi-auto-generated binding to C code/data (through RNA), which has its own rules and limitations on top of python C API.<br class=""><br class=""> Bastien<br class=""><br class=""><br class=""> On 05/11/2018 18:37, Benjamin Humpherys wrote:<br class=""><br class=""> I saw on the recent changes page on the wiki that the object selection API (<a href="https://wiki.blender.org/wiki/Reference/Release_Notes/2.80/Python_API/Scene_and_Object_API#Object_Selection_and_Hiding" class="">https://wiki.blender.org/wiki/Reference/Release_Notes/2.80/Python_API/Scene_and_Object_API#Object_Selection_and_Hiding</a>) has changed from a simple `<a href="http://obj.select/" class="">obj.select</a>` property to `select_get()` and `select_set(’SELECT’)`. I strongly urge this decision to be reconsidered because it is not idiomatic Python to use getter and setter functions, let alone setting a boolean property with a string argument!<br class=""><br class=""> Instead of getters and setters please consider making `select` a @property, or utilizing `PyGetSetDef`(<a href="https://docs.python.org/3/c-api/structures.html#c.PyGetSetDef" class="">https://docs.python.org/3/c-api/structures.html#c.PyGetSetDef</a>) to hide any new getter/setter logic instead of putting it in the user-facing API.<br class=""><br class=""><br class=""><hr class=""><br class=""> Bf-python mailing list<br class=""> <a href="mailto:Bf-python@blender.org" class="">Bf-python@blender.org</a><br class=""> <a href="https://lists.blender.org/mailman/listinfo/bf-python" class="">https://lists.blender.org/mailman/listinfo/bf-python</a><br class=""><br class=""><br class=""><hr class=""><br class=""> Bf-python mailing list<br class=""> <a href="mailto:Bf-python@blender.org" class="">Bf-python@blender.org</a><br class=""> <a href="https://lists.blender.org/mailman/listinfo/bf-python" class="">https://lists.blender.org/mailman/listinfo/bf-python</a><br class=""><br class=""><hr class=""><br class=""> Bf-python mailing list<br class=""> <a href="mailto:Bf-python@blender.org" class="">Bf-python@blender.org</a><br class=""> <a href="https://lists.blender.org/mailman/listinfo/bf-python" class="">https://lists.blender.org/mailman/listinfo/bf-python</a><br class=""></blockquote><br class=""><br class=""></pre></blockquote></div><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">--<span class="Apple-converted-space"> </span></span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">Sent from my Android device with K-9 Mail. Please excuse my brevity.</span><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">_______________________________________________</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">Bf-python mailing list</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><a href="mailto:Bf-python@blender.org" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">Bf-python@blender.org</a><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><a href="https://lists.blender.org/mailman/listinfo/bf-python" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">https://lists.blender.org/mailman/listinfo/bf-python</a></div></blockquote></div><br class=""></div></div></div></div></div></div></div></div></div></div></div></div></body></html>