-
Notifications
You must be signed in to change notification settings - Fork 2
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
Prototype of BFT abstractions and Streamlet; add static type checking #22
Conversation
Signed-off-by: Daira Emma Hopwood <[email protected]>
|
||
for i in range(2): | ||
proposal = PermissionedBFTProposal(current) | ||
self.assertTrue(proposal.is_valid()) |
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.
self.assertTrue(proposal.is_valid()) | |
proposal.assert_valid() | |
self.assertTrue(proposal.is_valid()) |
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.
Why are both lines necessary? Is this "verification-in-depth" which redundantly checks the same condition through different code paths, or are those checks intentionally distinct?
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.
We call proposal.assert_valid()
first because if the proposal is (incorrectly) not valid, that will tell us why — whereas is_valid()
will catch the exception and lose error information. Then we test that is_valid()
is implemented correctly for the True case.
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.
I still don't understand the second statement.
Aren't the two lines entirely equivalent, so long as assert_valid
is defined as follows?
def assert_valid(self):
assert self.is_valid()
I just looked it up, and it seems equivalent, though the dependency is inverted so we have:
def is_valid(self) -> bool:
"""Is this proposal valid?"""
try:
self.assert_valid()
return True
except AssertionError:
return False
My question is "is there ever a case where assert_valid
and is_valid
will not be entirely equivalent modulo boolean return vs raising AssertionError?
That could be the case if a subclass of PermissionedBFTProposal
overrides both methods and makes them logically non-equivalent. So I would refine my question to these two clauses:
- Is it possible / useful for subclasses to override these two methods in a manner in which they aren't logically equivalent (modulo raise-vs-return)?
- If not, is the purpose of these two lines to ensure all subclasses have implemented those two methods as logically equivalent (module raise-vs-return)?
If the answer to the first clause is 'no', then we could add a doc string or maybe a type signature to def is_valid
to prohibit overriding that method as a maintenance improvement / clarification.
Signed-off-by: Daira Emma Hopwood <[email protected]>
Signed-off-by: Daira Emma Hopwood <[email protected]>
Signed-off-by: Daira Emma Hopwood <[email protected]>
460715e
to
0163018
Compare
Signed-off-by: Daira Emma Hopwood <[email protected]>
Signed-off-by: Daira Emma Hopwood <[email protected]>
0163018
to
07142cf
Compare
Co-authored-by: Nate Wilcox <[email protected]> Signed-off-by: Daira Emma Hopwood <[email protected]>
297a96b
to
01aa384
Compare
01aa384
to
3a05300
Compare
Enforce the annotations in `check.sh` using `pyanalyze`. Signed-off-by: Daira Emma Hopwood <[email protected]>
Signed-off-by: Daira Emma Hopwood <[email protected]>
3a05300
to
76ef14a
Compare
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.
UtACK, with one (repeated) clarification question.
Type annotations are super helpful for me! Thanks.
|
||
for i in range(2): | ||
proposal = PermissionedBFTProposal(current) | ||
self.assertTrue(proposal.is_valid()) |
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.
Why are both lines necessary? Is this "verification-in-depth" which redundantly checks the same condition through different code paths, or are those checks intentionally distinct?
fixes #6
fixes #23