[Resolved] Problem in Extensions when adding multiple python ones

Here's the place for discussion related to coding in FreeCAD, C++ or Python. Design, interfaces and structures.
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
ickby
Veteran
Posts: 3116
Joined: Wed Oct 05, 2011 7:36 am

[Resolved] Problem in Extensions when adding multiple python ones

Post by ickby »

Hello,

I've noticed a flawed implementation in the current Extension code (written and messed up by myself :oops: ). The problem comes from the python side of things. I've made a bug report issue #4534 and here is the detailed description:

Adding a python extension creates the ExtensionProxy property, which is set to the default value passed in the addExtension method. This property belongs to the extension (defined here), and is exposed as an property for the object. The problem arises when a second python extension is added to the same object. In FC the extension itself gets the ExtensionProxy setup correctly in the addExtension method, as this method directly accesses the extension to get the property (see). However, now there are two ExtensionProxy' properties in the object, one for each extension. Accessing it from python will return only one, the first one that is found (see here).

This leads to the FreeCAD bug, that you cannot change the ExtensionProxy correctly for more than one extension. Note that neither in 0.18 or 0.19 this ever occured as bug, as no one seem to use more than 1 extension and also not the ExtensionProxy and just rely on addExtension. However, it could lead to all kind of unexpected behavior later.

Reproduce:

Code: Select all

	class Proxy1():
        def init(self):
            pass

class Proxy2():
        def init(self):
            pass

p1 = Proxy1()
p2 = Proxy2()
obj = App.ActiveDocument.addObject("App::DocumentObject", "MyObject")
obj.addExtension("App::GroupExtensionPython", p1)
obj.addExtension("Part::AttachExtensionPython", p2)

print(f"ExtensionProxy is Proxy1: {isinstance(obj.ExtensionProxy, Proxy1)}")
print(f"ExtensionProxy is Proxy2: {isinstance(obj.ExtensionProxy, Proxy2)}")
Solution Paths:
Now to be honest adding the ExtensionProxy to the extension was a stupid idea, and I think this approach is fundamentally flawed. There needs to be a single proxy for all python extensions to avoid any ambiguity. As the extensions are already in FC0.18 some thougth about backward compatibility are required.

Solution 1: Add ExtensionProxy to FeaturePython
This is the simplest fix, just remove extension proxy from all python extensions and make it a default property for FeaturePython. Than all extensions access their objects Extension proxy. I think this should keep all file compatibility. I did not find any use of two extensions in a object, hence unifying them should not make any trouble. However, there could theoretically be some code out there not working with this unification.

Solution 2: Drop ExtensionProxy and use the normal python Proxy instead.
It turns out that no one uses ExtensionProxy property for anything, currently the proxys are all set within the addExtension method. Furthermore I did not find any instance in FreeCAD source where Proxy != ExtensionProxy. Hence one can simply drop the property and use the normal python Proxy instead. This is a small problem for file compatibility, as loading old files need to drop a property. Also it could lead to some additional problems in external code when ExtensionProxy != Proxy.

Problems:
Both Solutions make some incompatible design changes as described in the individual solutions. Additionally the "addExtension" method would need to change, and the second extensionproxy argument needs to be dropped. This of course is used on FC and some addons. So one could either remove the second argument fully, and let everyone change the code. Or maybe for now make it optional and just ignore the argument and print a deprecation method for the next release (easier for developers, more annoying for users seeing it)

Summary: Qestions to be answered
  • Should the problem be solved or keept as is for minimal impact on external code?
  • Use unified ExtensionProxy or general Proxy property?
  • Change addExtension to be incompatible to 0.18 or use deprication warning?
  • Any better Solutions I've overlooked?
I'm going to implement the changes once we decided on a good way forward. Personally I prefer Solution 2: more impact, but more elegant afterwards.

Regards,
Stefan
ickby
Veteran
Posts: 3116
Joined: Wed Oct 05, 2011 7:36 am

Re: Problem in Extensions when adding multiple python ones

Post by ickby »

Here a pull request as basis for discussion, which implements Solution 2 with full API incompatibility: Remove ExtensionProxy and drop the argument from "addExtension"

Pull Request
ickby
Veteran
Posts: 3116
Joined: Wed Oct 05, 2011 7:36 am

Re: Problem in Extensions when adding multiple python ones

Post by ickby »

If no-one has any objections I like to get the PullRequest merged.
User avatar
Kunda1
Veteran
Posts: 13434
Joined: Thu Jan 05, 2017 9:03 pm

Re: Problem in Extensions when adding multiple python ones

Post by Kunda1 »

Bump
Alone you go faster. Together we go farther
Please mark thread [Solved]
Want to contribute back to FC? Checkout:
'good first issues' | Open TODOs and FIXMEs | How to Help FreeCAD | How to report Bugs
hyarion
Posts: 139
Joined: Fri Jun 26, 2020 6:08 pm

Re: Problem in Extensions when adding multiple python ones

Post by hyarion »

Kunda1 wrote: Tue Mar 02, 2021 11:41 pmBump
It's merged already
ickby
Veteran
Posts: 3116
Joined: Wed Oct 05, 2011 7:36 am

Re: [Resolved] Problem in Extensions when adding multiple python ones

Post by ickby »

yes, luckily werner was kind enough to bring the fix in before 0.19. I marked the title resolved.
User avatar
Kunda1
Veteran
Posts: 13434
Joined: Thu Jan 05, 2017 9:03 pm

Re: [Resolved] Problem in Extensions when adding multiple python ones

Post by Kunda1 »

Awesome!
git commit 446ce215
Thanks @ickby!
(thanks @hyarion for heads-up)
Alone you go faster. Together we go farther
Please mark thread [Solved]
Want to contribute back to FC? Checkout:
'good first issues' | Open TODOs and FIXMEs | How to Help FreeCAD | How to report Bugs
carlopav
Veteran
Posts: 2062
Joined: Mon Dec 31, 2018 1:49 pm
Location: Venice, Italy

Re: Problem in Extensions when adding multiple python ones

Post by carlopav »

ickby wrote: Tue Jan 26, 2021 6:10 am If no-one has any objections I like to get the PullRequest merged.
Hello, if we are using the addExtension method with just one argument, do we have to add something to the code for backward compatibility?
(I'm working on BIM workbench and I have a couple of

Code: Select all

obj.addExtension('Gui::ViewProviderGeoFeatureGroupExtensionPython', None) 
that I probably have to substitute with

Code: Select all

obj.addExtension('Gui::ViewProviderGeoFeatureGroupExtensionPython')
)

thank you @ickby
follow my experiments on BIM modelling for architecture design
ickby
Veteran
Posts: 3116
Joined: Wed Oct 05, 2011 7:36 am

Re: [Resolved] Problem in Extensions when adding multiple python ones

Post by ickby »

Yes, you should. In 0.19 the old syntax still works, but the second argument is unused. It does print a deprecation warning into the report view. So even for 0.19 it is recommended to change the code, as it is strange for the user to see. Later the second argument will be removed fully.

Note that it is still required in 0.18, hence you may need different code dependent on version if you want to support older freecad versions
carlopav
Veteran
Posts: 2062
Joined: Mon Dec 31, 2018 1:49 pm
Location: Venice, Italy

Re: [Resolved] Problem in Extensions when adding multiple python ones

Post by carlopav »

Ok! Thanks.
follow my experiments on BIM modelling for architecture design
Post Reply