-
Notifications
You must be signed in to change notification settings - Fork 85
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
Add user-facing Expression for composing a graph of observers #1067
Conversation
Codecov Report
@@ Coverage Diff @@
## master #1067 +/- ##
==========================================
- Coverage 76.15% 73.20% -2.96%
==========================================
Files 54 67 +13
Lines 6493 8159 +1666
Branches 1263 1558 +295
==========================================
+ Hits 4945 5973 +1028
- Misses 1205 1807 +602
- Partials 343 379 +36
Continue to review full report at Codecov.
|
…ackage but private outside of it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me.
Could we tweak/augment the API so that it's possible to create an |
@mdickinson Are these what you are looking for?: traits/traits/observers/expressions.py Lines 541 to 551 in 59d8769
Here is an example of the usage:
( expressions is the module here).
|
@kitchoi Thanks, but not really. It's the awkwardness of creating an I'm finding it hard to wrap my head around what an I think what I expect isn't a world away from what you have; it may be mostly a matter of naming. I think what we want is three top-level classes I think your I'd also expect these expression objects to be immutable; it looks as though they effectively are already in this PR: the only point at which they're being mutated is immediately after creation. We could remove the need to mutate entirely by adding suitable initialization logic to the And if they're immutable, then we don't have any need to copy things. (I'm not quite clear on why there are copies going on at the moment.) Take a look at the structure of Python's AST module (maybe just the expression piece) for inspiration; I think that's the sort of structure that we want here, though obviously it'll be much much simpler. |
IOW, what I think we want here is a Python-level representation of the following abstract data type (see e.g. https://en.wikipedia.org/wiki/Algebraic_data_type):
Python unfortunately doesn't have GADTs or unions or generalised Enum types like other languages, so the natural "Pythonic" way to represent the above datatype is using three separate classes |
traits/observers/expressions.py
Outdated
""" Return true if the other value is an Expression with equivalent | ||
content. | ||
|
||
e.g. ``(trait("a") | trait("b")) == (trait("b") | trait("a"))`` will |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this extra complication? I think I'd expect equality for an Expression
simply to be structural equality.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is merely for the users. As a user, I would expect trait("a") | trait("b")
and trait("b") | trait("a")
to be equivalent. It also does not hurt to make them not equal though. Nothing else depend on this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overlooked this :(. See #1080
Naming nitpick: I suggest |
@mdickinson Thank you for the review and suggestions. The Maybe we will need this |
So ignoring naming, the difference is that I'd like I'm suggesting an So again modulo naming, I think we want to restructure into 4 classes: the current I think we can make the structure and logic more obvious here, which would help future maintainers working with this code. |
@kitchoi Please open an issue for addressing the refactoring of the |
For the record, I gave the restructuring a go on my test branch: However this test branch does not have recursion feature that we have decided to delay. In other words, I have not tested the new structure with recursion support. From previous experience, recursion support has a fundamental influence on the data structures. I am confident that any of these restructuring will not affect public facing API. |
I will however make |
Merging now so that we can proceed with the next step. |
Closes #1024
Item 4 of #977
This PR adds the
Expression
class which allows user to compose a graph of items to be observed. No specific observers are included here, so the Expression at the moment isn't very useful. A proof-of-concept of this was previously implemented in #969.__or__
for combining two expressions to share the same parent, needed for"a, b"
then
for combining two expressions so that the latter expression is the child of the former one, needed for"a.b"
in the mini-language__eq__
for comparing two expressions- In fact, this is merely for the convenience of the users and for testing. For the user, one can do things like
parse("a,b") == parse("b, a")
and this helps learning the expression logic. For tests, the equality is useful for testing the mini-language parser later.After this PR, we can easily add the wrapper for each specific observer independently and the Expression class will become more useful.
e.g. like this:
traits/poc/expressions.py
Lines 157 to 180 in b8991fb
Checklist
docs/source/traits_api_reference
)Update User manual (docs/source/traits_user_manual
)Update type annotation hints in: We can have annotation hints for the high-level functions liketraits-stubs
trait
andmetadata
. This PR does not introduce those yet.