Page 1 of 1

Correct use of PropertyLinkSub - 'NoneType' object is not subscriptable

Posted: Sun May 15, 2022 1:34 pm
by Aleks
I have created a FeaturePython object and attached a vertex subobj to it with PropertyLinkSub

I get the following error at object creation, but not on object changes.

Code: Select all

15:13:42  Traceback (most recent call last):
  File "C:/Users/Aleksander/AppData/Roaming/FreeCAD/Macro\uselessbox.py", line 27, in execute
    link_sub = obj.LinkSub[0]
<class 'TypeError'>: 'NoneType' object is not subscriptable
This is the object code:

Code: Select all

class UselessBox():

    def __init__(self, obj):
        """
        Default constructor
        """

        self.Type = 'box'

        obj.Proxy = self

        obj.addProperty('App::PropertyString', 'Description', 'Base', 'Box description').Description = "Just a simple box"
        obj.addProperty('App::PropertyLength', 'Length', 'Dimensions', 'Box length').Length = 10.0
        obj.addProperty('App::PropertyLength', 'Width', 'Dimensions', 'Box width').Width = 5.0
        obj.addProperty('App::PropertyLength', 'Height', 'Dimensions', 'Box height').Height = 10.0
        obj.addProperty("App::PropertyLinkSub", "LinkSub", "Subsection", "Description for tooltip").LinkSub = None

    def execute(self, obj):
        """
        Called on document recompute
        """
        # get the parent document object containing the subobject
        link_sub = obj.LinkSub[0]
        # get the list of sub object names from the LinkSub Property
        sub_obj_name_list = obj.LinkSub[1]
        # get the first name in the sub object name list
        sub_obj_name = sub_obj_name_list[0]
        # get the actual sub object by its name
        vertex = link_sub.getSubObject(sub_obj_name)

        vtx_vector = App.Vector(vertex.X - (obj.Length.Value * 0.5), vertex.Y  - (obj.Width.Value * 0.5), vertex.Z  - (obj.Height.Value * 0.5))

        obj.Shape = Part.makeBox(obj.Length, obj.Width, obj.Height, vtx_vector)


def create():
    """
    Object creation method
    """

    obj = App.ActiveDocument.addObject('Part::FeaturePython', 'UselessBox')

    UselessBox(obj)

    obj.ViewObject.Proxy = 0 # just set it to something different from None (this assignment is needed to run an internal notification)

    App.ActiveDocument.recompute()

    return obj

Re: Correct use of PropertyLinkSub - 'NoneType' object is not subscriptable

Posted: Sun May 15, 2022 1:41 pm
by Aleks
I suspect its because of this line, when the PropertyLinkSub gets assigned None. The LinkSub property gets assigned a real subobj shape later on.:

Code: Select all

obj.addProperty("App::PropertyLinkSub", "LinkSub", "Subsection", "Description for tooltip").LinkSub = None
But I dont know what to do, so this error does not come up.

Re: Correct use of PropertyLinkSub - 'NoneType' object is not subscriptable

Posted: Sun May 15, 2022 1:51 pm
by Aleks
Nevermind, I just passed the values to the custom obj class on object creation.

Code: Select all

class UselessBox():

    def __init__(self, obj, sub_parent_obj, sub_elem_name):
        """
        Default constructor
        """

        self.Type = 'box'

        obj.Proxy = self

        obj.addProperty('App::PropertyString', 'Description', 'Base', 'Box description').Description = "Just a simple box"
        obj.addProperty('App::PropertyLength', 'Length', 'Dimensions', 'Box length').Length = 10.0
        obj.addProperty('App::PropertyLength', 'Width', 'Dimensions', 'Box width').Width = 5.0
        obj.addProperty('App::PropertyLength', 'Height', 'Dimensions', 'Box height').Height = 10.0
        obj.addProperty("App::PropertyLinkSub", "LinkSub", "Subsection", "Description for tooltip").LinkSub = [sub_parent_obj, sub_elem_name]

Re: Correct use of PropertyLinkSub - 'NoneType' object is not subscriptable

Posted: Mon Sep 19, 2022 5:07 am
by warnerjonn
Aleks wrote: Sun May 15, 2022 1:34 pm <class 'TypeError'>: 'NoneType' object is not subscriptable
The error is self-explanatory. You are trying to subscript an object which you think is a list or dict, but actually is None (i.e: the object has no value). This means that you tried to do:

None[something]

Here you attempted to index an object that doesn’t have that functionality. You might have noticed that the method sort() that only modify the list have no return value printed – they return the default None. This is a design principle for all mutable data structures in Python.

This ‘NoneType’ object is not subscriptable is the one thrown by python when you use the square bracket notation object[key] where an object doesn’t define the getitem method.

Re: Correct use of PropertyLinkSub - 'NoneType' object is not subscriptable

Posted: Mon Sep 19, 2022 8:19 am
by onekk
Aleks wrote: Sun May 15, 2022 1:34 pm

Code: Select all

link_sub = obj.LinkSub[0]

You are assuming that a:

Code: Select all

obj.LinkSub
property exist, that is a list and that is as at least one element.

But sadly when the error is raised:

Code: Select all

obj.LinkSub


is not existing so ti have a NoneType.

probably chceking if:

Code: Select all

obj.LinkSub
is set or maybe setting it to an empty list (if applicable) would do the job.

Such error are very hard to catch when you are coding, as you usually test them "knowing what to do" so probably if you assign a proper value no error is raised.

Sadly these type of errors are usually found by the "end user" after the whole code is perfectly tested and is "running smoothly" :oops:.

I usually assign None only to flags value or usually assign them to False directly.

If the value is a list itvery easy to check it with:

Code: Select all

if len(something) > 0
	do somthing
else:
	 # it depends on the context, possibly something like:
	 return
	 exit
	 break
	 something = [""] # an empty value
	 # raise an error
	 # print a "wrong value message"

Hope it helps.

Regards

Carlo D.