-
Notifications
You must be signed in to change notification settings - Fork 122
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
test: add type hints to test_framework #1025
test: add type hints to test_framework #1025
Conversation
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.
Looks good, thanks. A couple of questions and a few small changes requested.
test/test_framework.py
Outdated
self.assertIn( | ||
"WARNING:ops.framework:deprecated: Framework now takes a Storage not a path", | ||
cm.output) | ||
self.assertIsInstance(framework._storage, SQLiteStorage) | ||
|
||
def test_handle_path(self): | ||
cases = [ | ||
(ops.Handle(None, "root", None), "root"), | ||
(ops.Handle(None, "root", 'test1'), "root[test1]"), |
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.
Unless I'm missing something, I'm a bit nervous that we're changing / removing these test cases. If anything I think we should keep the existing ones (changing the typing shouldn't change them) and add a couple of new ones testing the additional cases.
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.
The Handle.__init__
code is like this:
def __init__(self, parent: Optional[Union['Handle', 'Object']], kind: str, key: str):
...
self._key = key
...
if key:
self._path = f"{parent}/{kind}[{key}]"
else:
self._path = f"{parent}/{kind}"
The docs say (my emphasis):
The handle key is a string uniquely identifying the object.
The key is also used for hashing and equality checks (None
is fine in either of those situations, but so are other non-string things). It's also a public member, and I don't have the experience to know how that's generally used, however, it does claim to be a string as well:
@property
def key(self) -> str:
This seems messy to me. Shouldn't we either have the type signature and documentation match the behaviour and accept str|None
(the docs could say that this should not be done), or have the implementation match the type signature and documentation and reject None
as an invalid value for key
(maybe this is tricky with backwards compatibility?)?
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.
Hmm, yeah. From looking at the code, I think key
should have been an Optional[str]
all along -- the fact that is was typed as str
was I think an oversight. The if key
would handle empty string as well, but I think None
would be the intention.
I've found one charm that passes None
as the key
argument to Handle
.
So I think we should change Handle
's key arg to Optional[str]
, and same for nest
's key argument. Those should be perfectly backwards-compatible changes, as we're expanding the type.
I also think we should change the key
property's type to be Optional[str]
. That isn't quite a backward-compatible change (typing-wise), because code that accesses the property will then have to assert key is not None
to type check. But I've done a quick search and I can't see any charms using that property (it's a bit advanced/arcane to use Handle
directly in the first place, let alone access handle.key
).
So I think it's safe to change and we should do it. If you want, we could start a file CHANGES.txt
that we use to record notes and breaking changes for the upcoming release, so we remember.
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.
Done - lmk if you'd prefer a particular format for the changes file.
(via code review).
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.
All looks good, thanks!
Handle
'skey
(in__init__
andnest()
and the property) to explicitly allow `NoneBoundStoredState.__getattr__
- multiple overloads need to be provided, and once that's done the ignores can be removed (and a bunch of type issues in the tests get resolved)None
Partially addresses #1007