-
Notifications
You must be signed in to change notification settings - Fork 192
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
👌 IMPROVE: Entity Collection typing #5183
👌 IMPROVE: Entity Collection typing #5183
Conversation
Codecov Report
@@ Coverage Diff @@
## develop #5183 +/- ##
===========================================
+ Coverage 80.97% 81.00% +0.03%
===========================================
Files 535 535
Lines 37201 37289 +88
===========================================
+ Hits 30120 30201 +81
- Misses 7081 7088 +7
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
Note, you can do: NodeType = TypeVar('NodeType', bound='Node')
class NodeCollection(EntityCollection[NodeType], Generic[NodeType]): Then using e.g. @classproperty
def objects(cls: Type[NodeType]) -> NodeCollection[NodeType]: ends up with Edit, as noted in python/mypy#2563 (comment), if you change ReturnType = TypeVar('ReturnType')
ClsType = TypeVar('ClsType')
class classproperty(Generic[ReturnType]): # pylint: disable=invalid-name
"""
A class that, when used as a decorator, works as if the
two decorators @property and @classmethod where applied together
(i.e., the object works as a property, both for the Class and for any
of its instance; and is called with the class cls rather than with the
instance as its first argument).
"""
def __init__(self, getter: Callable[[Type[ClsType]], ReturnType]) -> None:
self.getter = getter
def __get__(self, instance: Any, owner: Type[ClsType]) -> ReturnType:
return self.getter(owner) It does now give Pylance introspection also works... kind of. now implemented |
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.
Thanks @chrisjsewell , just some minor changes, some questions for clarification and one potential problem which was already there and your PR doesn't change, so this could be left for another time but wanted to raise it here in case you have an idea already.
Co-authored-by: Sebastiaan Huber <mail@sphuber.net>
Thanks @chrisjsewell merge away |
This PR makes static types available for
Entity.ojects
.As an example, in
pyproject.toml
comment outfollow_imports
:and run
example.py
against mypy (with the pre-commit env loaded):One thing to note above, is that entity subclass methods give base-class entity types,(fixed, see below)Data.objects.get() -> Node
.Ideally this would give
Data
, but I haven't been able to work this out (it is already tricky enough, with the cyclic nature ofEntity -> Collection -> Entity ...
😬)To stress, this is only an issue with the static typing, not the actual runtime return types.
A few points:
Collection
sub-classes are now defined outside of theEntity
sub-classes. There is no reason why they cannot be used independent of theEntity
itself.Entity.Collection
attribute, for back-compatibility, but actually it is no longer needed.aiida/common/datastructures::LazyStore
has been removed and replaced with https://docs.python.org/3/library/functools.html#functools.lru_cache. Caching was added due to Add caching of object collections #2216; I'm interested if it really speeds things up that much, but also there's no downside to keeping it.You can view it working with:
Comment.objects
that were fixed to ensure theCollection
uses the same backend as theEntity
, e.g.Comment.objects(self.backend)
pylint_aiida
plugin #5182 ensures e.g.Node.objects.get
uses don't raise (incorrect)no-member
issues in pylintUser.get_or_create
returns the opposite way toComputer
orGroup
, i.e.Tuple[bool, 'User']
, notTuple['User', bool]
. But I don't see away to deprecate that 🤷