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

Add a dummy object to designate "uninitialized" networks (fixes #511) #525

Merged
merged 17 commits into from
Oct 17, 2024

Conversation

acolomb
Copy link
Collaborator

@acolomb acolomb commented Aug 7, 2024

This class can replace the dummy "None" value for attribute initializations, which can then be properly typed as Network to avoid static type checking errors.

Switch to that new initialization in the NmtBase class as an example.

This has the benefit of not needing self.network is not None checks at run-time wherever a method or attribute access is used, but still satisfies static type checking. When hitting such a code path at run-time, of course it will lead to an exception because the attributes required in the Network methods are not set. But that is a case of wrong API usage (accessing a network without associating it first), which a static checker cannot detect reliably. The dummy class could be modified to provide a better exception message if desired, but this is just a minimal proof of concept so far.

This is an alternative approach to #513. If the concept looks acceptable, it will be extended to other places with the same type checker errors.

This class can replace the dummy "None" value for attribute
initializations, which can then be properly typed as Network to avoid
static type checking errors.

Switch to that new initialization in the NmtBase class as an example.

This has the benefit of not needing `self.network is not None` checks
at run-time wherever a method or attribute access is used, but still
satisfies static type checking.  When hitting such a code path at
run-time, of course it will lead to an exception because the
attributes required in the Network methods are not set.  But that is a
case of wrong API usage (accessing a network without associating it
first), which a static checker cannot detect reliably.  The dummy
class could be modified to provide a better exception message if
desired, but this is just a minimal proof of concept so far.
This works because `from foo import bar` requires full module
initialization at import time, while simply importing the module name
does not.
@acolomb
Copy link
Collaborator Author

acolomb commented Aug 7, 2024

@erlend-aasland What do you think of this approach, before I start fleshing it out in more detail?

@erlend-aasland
Copy link
Contributor

@erlend-aasland What do you think of this approach, before I start fleshing it out in more detail?

I'm not totally convinced, but I like it better than sprinkling the code with conditionals.

@codecov-commenter
Copy link

codecov-commenter commented Aug 11, 2024

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

Attention: Patch coverage is 83.33333% with 7 lines in your changes missing coverage. Please review.

Project coverage is 71.37%. Comparing base (6bc90a8) to head (bd8b4ea).

Files with missing lines Patch % Lines
canopen/node/local.py 40.00% 6 Missing ⚠️
canopen/network.py 83.33% 1 Missing ⚠️

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #525      +/-   ##
==========================================
+ Coverage   71.16%   71.37%   +0.21%     
==========================================
  Files          26       26              
  Lines        3114     3130      +16     
  Branches      527      480      -47     
==========================================
+ Hits         2216     2234      +18     
+ Misses        766      765       -1     
+ Partials      132      131       -1     
Files with missing lines Coverage Δ
canopen/emcy.py 97.22% <100.00%> (+0.03%) ⬆️
canopen/lss.py 41.75% <100.00%> (+0.32%) ⬆️
canopen/nmt.py 91.91% <100.00%> (+0.05%) ⬆️
canopen/node/base.py 100.00% <100.00%> (ø)
canopen/node/remote.py 67.46% <100.00%> (+0.80%) ⬆️
canopen/pdo/base.py 65.24% <100.00%> (+0.26%) ⬆️
canopen/sdo/base.py 82.97% <100.00%> (+0.18%) ⬆️
canopen/network.py 90.00% <83.33%> (-0.31%) ⬇️
canopen/node/local.py 85.54% <40.00%> (+0.35%) ⬆️

... and 2 files with indirect coverage changes

Use a _DummyNetwork object instead.  Fix up check for "network is
None" by providing a convenience has_network() function in the base
class.
@acolomb acolomb marked this pull request as ready for review August 11, 2024 21:34
Use a _DummyNetwork object instead.
canopen/network.py Outdated Show resolved Hide resolved
canopen/node/local.py Outdated Show resolved Hide resolved
Copy link
Contributor

@erlend-aasland erlend-aasland left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this!

canopen/network.py Outdated Show resolved Hide resolved
@erlend-aasland
Copy link
Contributor

(You need to amend the PR title to reflect the name changes.)

@acolomb acolomb changed the title Add a _DummyNetwork class to designate "uninitialized" networks Add a dummy object to designate "uninitialized" networks Aug 12, 2024
@acolomb
Copy link
Collaborator Author

acolomb commented Aug 12, 2024

@sveinse Are you satisfied with this solution instead of #513?

@acolomb acolomb changed the title Add a dummy object to designate "uninitialized" networks Add a dummy object to designate "uninitialized" networks (fixes #511) Aug 13, 2024
@acolomb
Copy link
Collaborator Author

acolomb commented Oct 15, 2024

Gentle ping @sveinse, I'm still waiting on your opinion. If you're currently not able to invest much time, please say so. Two contributors with a preference to accept this PR is enough for me, just didn't want to pass you over.

Copy link
Collaborator

@sveinse sveinse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@acolomb thank you for the ping. I think this solution is the best of the non-perfect solutions. The alternative would be to pepper with network: Optional[Network] = None and having to deal with the None to instruct the linter what it should be. Using this object shows intent and it will fail if it's tried used without initialization. PR Approved.

Sorry for not responding, I'm in a terrible busy phase @work so I have limited time. Thanks for the involvement thou.

@acolomb acolomb merged commit c781a22 into christiansandberg:master Oct 17, 2024
3 checks passed
@acolomb acolomb deleted the dummy-network branch October 17, 2024 19:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Network instance is optional in many classes, which requires lot of checking
4 participants