[Link] of (Sketch)ObjectPython / Part FeaturePython lose its 'Proxy Methods' ?

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
User avatar
vanuan
Posts: 539
Joined: Wed Oct 24, 2018 9:49 pm

Re: [Link] of (Sketch)ObjectPython / Part FeaturePython lose its 'Proxy Methods' ?

Post by vanuan »

This is not healthy. App::Link as it exists now should be deprecated.

There should be a limit to what properties are available in a link.

If you need additional properties to be overridable, developers should inherit from App::Link: Part::LinkToFeature, Sketcher::LinkToSketcherObject, App::LinkToFeaturePython

Only this will ensure that Link behaves the same as the object it points to.
paullee
Veteran
Posts: 5130
Joined: Wed May 04, 2016 3:58 pm

Re: [Link] of (Sketch)ObjectPython / Part FeaturePython lose its 'Proxy Methods' ?

Post by paullee »

vanuan wrote: Sun Sep 06, 2020 12:00 pm This is not healthy. App::Link as it exists now should be deprecated.

There should be a limit to what properties are available in a link.

If you need additional properties to be overridable, developers should inherit from App::Link: Part::LinkToFeature, Sketcher::LinkToSketcherObject, App::LinkToFeaturePython

Only this will ensure that Link behaves the same as the object it points to.
Thanks for advice, can you elaborate ?

Not sure what to do, and haven' heard about App::Link: Part::LinkToFeature, Sketcher::LinkToSketcherObject, App::LinkToFeaturePython :D
User avatar
vanuan
Posts: 539
Joined: Wed Oct 24, 2018 9:49 pm

Re: [Link] of (Sketch)ObjectPython / Part FeaturePython lose its 'Proxy Methods' ?

Post by vanuan »

paullee wrote: Sun Sep 06, 2020 12:08 pm Thanks for advice, can you elaborate ?

Not sure what to do, and haven' heard about App::Link: Part::LinkToFeature, Sketcher::LinkToSketcherObject, App::LinkToFeaturePython :D
Those are just a suggestion. Something like this:

Code: Select all

class LinkToFeaturePython(App.Link):
  @property
  def LinkedObject(self) -> Part.FeaturePython:
    return super().LinkedObject

  @property
  def Proxy(self) -> App.DocumentObject:
    return copy(self.LinkedObject.Proxy)

  @property
  def Placement(self) -> App.Placement:
    if self.__placement:
      return self.__placement
    return copy(self.LinkedObject.Placement)
This requires inheritance from builtins to work properly (a different topic of discussion).

Mainly, I was answering the question "how to differentiate between properties of the Link itself from the properties of the Linked Object". If I were to design App.Link, my answer would be "use link.Placement and link.LinkedObject.Placement correspondingly".

But as how Link is designed now, this is just meaningless. I'm curious what realthunder has to say about your question.
realthunder
Veteran
Posts: 2190
Joined: Tue Jan 03, 2017 10:55 am

Re: [Link] of (Sketch)ObjectPython / Part FeaturePython lose its 'Proxy Methods' ?

Post by realthunder »

paullee wrote: Sun Sep 06, 2020 11:56 am [*] Suggestion / Feature Request - To add appLinkInit(self, obj, linkObj, index, linkElement)
Can you elaborate on when this will be called? When the object is assigned to Link?
[*] Adding Attribute counterpart to Link - Can same Attribute names be used?
(trying to use "Link"+Attribute, but complicate programming in relevant method)
[*] Trying to hide in Links those Attributes of the Linked Objects, but display counterpart Attributes in LinkedObject (see item 2 above). Found hiding Links.Attributes in Links also hide the same in LinkedObj[/b][/color]
To differentiate the properties that belong to Link and the linked object, you can use link.PropertiesList, this will give you a list of property names that actually belong to Link. A pending PR (or you can try my branch) also lets you do this using link.getPropertyByName(name, 1), which will raise exception if Link itself does not have a property by that name. And getPropertyByName(name, 2) will return a tuple(owner, property), giving you the actual owner object of the property.

Another PR (or with my branch), the property editor will also differentiate the linked property by showing them in green font. You can try adding a property with the same name of some linked property, and see the color change.
Try Assembly3 with my custom build of FreeCAD at here.
And if you'd like to show your support, you can donate through patreon, liberapay, or paypal
paullee
Veteran
Posts: 5130
Joined: Wed May 04, 2016 3:58 pm

Re: [Link] of (Sketch)ObjectPython / Part FeaturePython lose its 'Proxy Methods' ?

Post by paullee »

realthunder wrote: Mon Sep 07, 2020 1:19 am [Can you elaborate on when this will be called? When the object is assigned to Link?
Thanks !

May i elaborate the usecase and original Feature Python functionality.

Upon __Init__(), a few attributes are added for user's input. So, it seems whenever a link is assigned with a Linked Object, the Linked Object's appLinkInit() should be called.

Say, a few attributes -
- Edge No. to attach to
- X,Y, Z offset from end of edge user requires
The above are then 'instance' - specific.

Then, upon appLinkExecute, it execute same method to calculate each instances own placement.

The issue is for Link's attribute, it seems it needs to be named different - say 'LinkEdgeNo' from LinkedObject's 'EdgeNo', so that it could be operated, hidden or shown in editor etc. It is not very clean, as it needs the method to operate with both Attributes Name.


Then, i also find appLinkOnDocumentRestored() is needed as my Feature Python run a series of functions on Document Opening for it to function.

Seem onChanged() ... also.


These seems make a Link to Feature Python with all functionalities available not only the Shape. Hope it make sense.


Thanks
paullee
Veteran
Posts: 5130
Joined: Wed May 04, 2016 3:58 pm

Re: [Link] of (Sketch)ObjectPython / Part FeaturePython lose its 'Proxy Methods' ?

Post by paullee »

BTW, it seems Draft.getType() return "Unknown" for a Link.

Searching, checking getType() codes and testing, it seem Link.TypId return - 'App::Link'.

Is it enough to test an object's TypID to confirm it is a Link ? Maybe can add to Draft.getType() also if affirmative.

Thanks for any idea.
paullee
Veteran
Posts: 5130
Joined: Wed May 04, 2016 3:58 pm

Re: [Link] of (Sketch)ObjectPython / Part FeaturePython lose its 'Proxy Methods' ?

Post by paullee »

It seems it is more complicated and needs more knowledge in python and FC to implement what I thought, more issues noted :D

Following wiki about Scripted Objects and some Arch Objects, created some FeaturePython object and below codes in __init__ works, but not in Link. That is it seems can't e.g. add a dict or a string for that particular Link object. They were added for calculation of placement of the object.

Code: Select all

        self.objTag = ""
        self.objDict = {}
Any idea ?

Hope this is not a deadend :)
realthunder
Veteran
Posts: 2190
Joined: Tue Jan 03, 2017 10:55 am

Re: [Link] of (Sketch)ObjectPython / Part FeaturePython lose its 'Proxy Methods' ?

Post by realthunder »

paullee wrote: Mon Sep 07, 2020 5:49 am Then, i also find appLinkOnDocumentRestored() is needed as my Feature Python run a series of functions on Document Opening for it to function.

Seem onChanged() ... also.
If you really need so many callbacks, it is probably better to go the normal proxy route. But I don't think you need all these. And you don't really need to check the link type, because only Link will call your appLinkExecute(). You don't need appLinkInit(), because dynamic property can be removed by user. You might as well check it in execute. Here is an example. Let's not handle the more complex array situation just yet.

Code: Select all

def appLinkExecute(self, obj, linkObj, index, linkElement)
  properties = linkObj.PropertiesList
  # This is assuming all these properties you want to add exists in obj
  # You don't need to hide the original property. The action of adding a property of the same name will hide the linked property.
  for prop in [ ("XYZ", "MNO", "PQR" ]:
    if prop not in properties:
      linkObj.addProperty(obj.getTypeIdOfProperty(prop), prop, obj.getGroupOfProperty(prop))
      
   # now do what you like to calculate the placement using these properties through linkObj
   # linkObj.Placement = linkObj.XYZ.bla bla bla
Try Assembly3 with my custom build of FreeCAD at here.
And if you'd like to show your support, you can donate through patreon, liberapay, or paypal
paullee
Veteran
Posts: 5130
Joined: Wed May 04, 2016 3:58 pm

Re: [Link] of (Sketch)ObjectPython / Part FeaturePython lose its 'Proxy Methods' ?

Post by paullee »

realthunder wrote: Mon Sep 07, 2020 11:48 pm
Wow! I used hasattr() which seems did not distinguish LinkedObject's from Link's properties, so it did not work.

With linkObj.PropertiesList, now it works ! Each Link can now has its own property (App::PropertyLink in below example screencapture). 1st Problem Solved :lol:

Slightly different codes -
(works for LinkedObject and Links)

Code: Select all

  def setPropertiesLinkCommon(self, orgFp, linkFp=None):
      if linkFp:
          fp = linkFp
      else:
          fp = orgFp
      prop = fp.PropertiesList

      if "MasterSketch" not in prop:
          fp.addProperty("App::PropertyLink","MasterSketch","Referenced Sketches and Axis","Master Sketch to Attach on")

Then, it seems can't e.g. add a dict or a string for that particular Link object, they were needed as in original FeaturePython object for calculation of placement of the object.

Code: Select all

        self.objDict = {}
        self.objTag = ""
Thanks for any idea :)


realthunder wrote: Mon Sep 07, 2020 11:48 pm If you really need so many callbacks, it is probably better to go the normal proxy route.
What is 'Normal proxy route' ? :?:

Test_ Link_appLinkExecute_ 01.FCStd
(13.96 KiB) Downloaded 76 times
Screenshot from 2020-09-09 00-28-34.png
Screenshot from 2020-09-09 00-28-34.png (270.96 KiB) Viewed 2127 times
realthunder
Veteran
Posts: 2190
Joined: Tue Jan 03, 2017 10:55 am

Re: [Link] of (Sketch)ObjectPython / Part FeaturePython lose its 'Proxy Methods' ?

Post by realthunder »

paullee wrote: Tue Sep 08, 2020 4:37 pm Then, it seems can't e.g. add a dict or a string for that particular Link object, they were needed as in original FeaturePython object for calculation of placement of the object.

Code: Select all

        self.objDict = {}
        self.objTag = ""
Can you elaborate how you uses these two attributes in the original FeaturePython? If you need to save those attributes to document, then you can simply addProperty to link. If it is only for runtime use, just create a bigger dictionary in the original FeaturePython and key on link. You can include original object as key too,

Code: Select all

	self.links[linkObj] = ({}, '')
	
	#or use more fancy objects like namedtuple and default dict
	# MyStorage = namedtuple('MyStorage', ('objDict', 'objTag'), defaults=({}, ''))
	
	self.links = defaultdict(MyStorage)
	
	# then simply use it like
	self.links[linkObj].objDict.get('something')
Try Assembly3 with my custom build of FreeCAD at here.
And if you'd like to show your support, you can donate through patreon, liberapay, or paypal
Post Reply