Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Core] Allow properties owned by the document to be used in expressions #10653

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

AjinkyaDahale
Copy link
Contributor

@AjinkyaDahale AjinkyaDahale commented Sep 11, 2023

Draft PR. Nothing to see here, for now.

Addresses Ondsel-Development#5 but does not completely solve it (expression completion to follow in a separate PR).

There are two parts to this problem:

  1. make the lexer/parser understand we are passing a document property.
  2. make the expression engine use the value in expressions. Currently it expects that the property belongs to a document object.

@github-actions github-actions bot added the Mod: Core Issue or PR touches core sections (App, Gui, Base) of FreeCAD label Sep 11, 2023
@AjinkyaDahale AjinkyaDahale force-pushed the core-access-doc-properties-from-expressions branch 5 times, most recently from afea933 to ad61d58 Compare September 15, 2023 19:20
@AjinkyaDahale
Copy link
Contributor Author

@JohnAD the branch for expression engine.

@AjinkyaDahale AjinkyaDahale force-pushed the core-access-doc-properties-from-expressions branch 2 times, most recently from 855e773 to 3741ba7 Compare September 27, 2023 13:31
@AjinkyaDahale AjinkyaDahale force-pushed the core-access-doc-properties-from-expressions branch from 3741ba7 to e9262c6 Compare October 8, 2023 12:13
@yorikvanhavre
Copy link
Member

How is this one going @AjinkyaDahale ? Any progress?

@AjinkyaDahale
Copy link
Contributor Author

AjinkyaDahale commented Oct 9, 2023

How is this one going @AjinkyaDahale ? Any progress?

It's probably going to take a good while longer. The changes are quite deep and I haven't been able to get a compilable code before making all of the changes at the same time.

That said, @JohnAD was able to make some workaround which checks for the type of the property container solely in ObjectIdentifier. This could be a solution, but I don't know how it affects the rest of the code—Particularly the adjustLink(s) methods, and wherever they are called.

There is also an option of falling back to a "dummy" document object, but that is more inelegent than the present attempt.

@AjinkyaDahale AjinkyaDahale force-pushed the core-access-doc-properties-from-expressions branch from e9262c6 to 856c7e8 Compare October 11, 2023 12:15
@yorikvanhavre
Copy link
Member

I've been playing a bit with this here but cannot get any further than you 😅

@JohnAD
Copy link
Contributor

JohnAD commented Oct 16, 2023

As promised, an example of why both the document and the document properties need prefixes:

The user makes a new document:

  • He names the doc abc.
  • In that document, he sets a property called abc and another one called x.
  • He also builds adds a object in the Part workbench called abc and another one called x.
  • He sets the abc property to that abc object. And a subproperty of abc called x to 3.4.

What does abc.abc refer to?:

a. The document abc's property called abc
b. The document abc's object called abc?
c. The abc object property called abc?

Since we know document properties and document object names are separate namespaces (and can collide), we are already planning on having the document-properties having a hash prefix. So (a) above is now abc#abc. But object references are still ambigous. abc.abc: is the first abc a document or an object? or the property of an object?

What about abc.x or abc.abc.x or abc.abc.abc.x ?

In other words, the "document names" and "object name" namespaces will also collide.

So, if the document name always has a prefix, such as $. then thing become very blunt:

  • $abc#abc is document abc's property called abc.
  • $abc.abc is document abc's object called abc. (or better: $abc.abc.abc for the object property abc of object abc)
  • abc.abc is the "current document" object called abc's property called abc. (which is what works right now.)

And even:

#abc is the "current document" property called abc.
.abc is the "current document"'s "current object"'s property called abc.

Or even what is not allowed (yet):

#abc.abc is the "current document"'s property abc which has a sub-property called abc.

In the documentation we can simply explain the general rules: prefix document property names with #. Prefix documents with $.

@AjinkyaDahale
Copy link
Contributor Author

@JohnAD I see a bit clearer what you mean here. Of course we would need to make sure existing mechanisms are not broken. For example in abc#abc.abc, the first abc must be the document.

I have some doubts about what happens if some of the properties themselves evaluate to another document or document object. For example if $abc.abc were linking to another document def, would we be able to access things like $abc.abc#ghi ($def#ghi being an object belonging to def).

In the documentation we can simply explain the general rules: prefix document property names with #. Prefix documents with $.

I think you mean "prefix property name with ., prefix document object name with #, and prefix document name with $ (the character itself being up for debate)"?

@AjinkyaDahale AjinkyaDahale force-pushed the core-access-doc-properties-from-expressions branch 3 times, most recently from bd7717e to dec33cc Compare October 26, 2023 05:52
@AjinkyaDahale
Copy link
Contributor Author

@JohnAD I see a flaw here. Consider $abc.abc by your suggestion. Say abc is the current document name, and we wanted it to be the present document at all times. Then, for some reason, we rename the document abc2 (as a crude version control, say). Now, the engine is left searching for a document abc which, at best, doesn't exist (and errors happen), or, at worst, is the "older" version still kept in the same folder [1], with possibly an older version of the property (and the user is unaware and left troubleshooting).

[1] As such, we would also need a method to describe files from different folders.

@AjinkyaDahale AjinkyaDahale force-pushed the core-access-doc-properties-from-expressions branch from dec33cc to 7c60072 Compare October 27, 2023 11:02
@JohnAD
Copy link
Contributor

JohnAD commented Oct 27, 2023

I see what you are saying. We could possibly make an empty $ to mean "current document". So, to get a property of the current document, regardless of the document's name, use $#xyz. To get an object abc's def property, one could use $.abc.def.

Or we could be more explicit, perhaps an empty paren. So, $()#def and $().abc.def. But I would think the empty $ is more elegant.

@AjinkyaDahale AjinkyaDahale force-pushed the core-access-doc-properties-from-expressions branch 3 times, most recently from 6df5841 to eb1e625 Compare November 9, 2023 01:51
@AjinkyaDahale AjinkyaDahale force-pushed the core-access-doc-properties-from-expressions branch 3 times, most recently from aaab849 to 7e178eb Compare November 13, 2023 03:57
Also contains:

[Core] Some more attempts at identifying `$` token

[Core] Fix identifying `$` sign in parser
In collaboration with John Dupuy.

Finished Spreadsheet expression test; started on document property test

Finished document property expression binding test
Needed to support properties belonging to documents.
…dentifier`"

This reverts commit 855e773.

Keeping Graphviz changes and taking one step at a time.
From `DocumentObject` to `PropertyContainer`
So that Documents can also be containers.
@AjinkyaDahale AjinkyaDahale force-pushed the core-access-doc-properties-from-expressions branch from 7e178eb to 6a7fda5 Compare November 14, 2023 04:48
@pieterhijma
Copy link
Contributor

@AjinkyaDahale and @JohnAD, I think this is a great way to improve the parameter system. After studying the code, I agree this is a very challenging topic and should be done carefully, especially with compatibility issues in mind. I have some questions and comments.

Regarding the prefixes a first observation is that there are multiple interfaces to properties:

  • the expression engine
  • the Python interface

The discussion above only discusses the expression engine interface.

I think it makes sense to make a distiction between fully qualified names and partially qualified names.

Currently, the expression engine is "smart" in the sense that it automatically restores fully qualified names to partially qualified names. For example after making a Part Cube in a document saved as "mydoc.FCStd":

doc = App.ActiveDocument
doc.Box.addProperty("App::PropertyFloat", "MyProp")
doc.Box.MyProp = 6

Using the GUI to set the Length of the Box to mydoc#Box.MyProp, this expression is automatically changed to MyProp.

Making a second Cube and setting the length to mydoc#Box.MyProp, the expression is automatically shortened to Box.MyProp. So, apparently the expression engine has a sense of scope here and makes properties partially qualified automatically.

This only discusses the expression interface, but the Python interface should also be taken into account. In the example above doc.Box refers to the Cube object. But if we would add a property Box to the document, then in Python you would address this with doc.Box as well. To me this shows that it should simply be not possible to have a property and an object with the same (fully qualified) name.

Note that this is already the case in other parts of FreeCAD: I cannot make a property "Shape" in doc.Box for example, because there is already something called Shape there (the error message calls it "property" but I don't think that is technically correct):

>>> doc.Box.addProperty("App::PropertyFloat", "Shape")
Traceback (most recent call last):
  File "<input>", line 1, in <module>
...
'Property mydoc#Box.Shape already exists'
...

It is a bit strange that FreeCAD allows a property "Box" if there is already a "Box" object. By the way, in Python doc.Box refers to the property. The object can still be obtained by using doc.getObject("Box").

In my humble opinion the case for document properties should follow the same semantics as for object properties: it should not be possible to have properties with the same name as objects, so it should not be possible to make a property mydoc#Box if there is already a mydoc#Box object. The drawback of this is that it breaks backward-compatibility, but with a simple check, we could warn for that and potentially even fix it. I don't think there are many documents that have a document property with the same name as an object.

The benefit is that adopting these semantics make things much more simple.

So, following this logic, in my humble opinion, I don't see the need for an extra prefix in the expression engine: <document>#<property-or-object>(.<property-or-object>)* is clear enough where at resolution time, we figure out whether it is an object or a property.

Note that this is only valid if we are talking about fully qualified names. The problems arise when there is ambiguity in partially qualified names and I believe your additional prefix solution tries to address this problem as well. I think the way forward would be to default to fully qualified names internally and use other mechanisms for scoping than the expression engine now offers. This is another topic that is more fitting in the discussion of the issue Ondsel-Development#5 than in this conversation on this pull request, but in the context of this pull request mydoc#DocProp would simply refer to a document property, mydoc#Body would refer to a Part Design body.

Since I only took a look at the code while you have been actually working on it, I'm sure I missed something, so I'm looking forward to your comments.

@yorikvanhavre
Copy link
Member

I like @pieterhijma's idea...

It would solve a lot of issues (although it introduced s more work too), and it could be dealt with on a simple "first come first served" basis, same as when adding new objects. In case a name already exists, then we would have two different behaviours:

  • When adding a new object, if the name is already taken (by an object or a property), then the object name gets a '001' suffix
  • When adding a new property, if the name is already taken (by an object or a property), then an error is raised.

@pieterhijma
Copy link
Contributor

Dear all, I've created an issue for the problem that this PR addresses in the FreeCAD repo: #12120.

@maxwxyz
Copy link
Collaborator

maxwxyz commented May 15, 2024

@AjinkyaDahale @pieterhijma what's the status on this PR? Will it be resumed or replaced by VarSet?

If you want this draft PR to be considered for a version 1.0 release, it should be marked ready for review by Monday, 2024-06-03 at the latest. (further details in the 1.0 feature freeze forum announcement).

@maxwxyz maxwxyz added this to the Post 1.0 milestone Jul 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Mod: Core Issue or PR touches core sections (App, Gui, Base) of FreeCAD
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants