-
-
Notifications
You must be signed in to change notification settings - Fork 340
Implement type hints for Node subclasses #4793
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
base: master
Are you sure you want to change the base?
Conversation
| """Because we're a Python value node and don't have a real | ||
| timestamp, we get to ignore the calculator and just use the | ||
| value contents. | ||
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 closest thing to a "functional" change this PR was removing this optional argument. This is the only instance of get_csig taking an extra argument, and it's completely unused. Based of the docstring, I assume every get_csig took a calc argument at one point, with Value specifically treating it as a no-op; that might be why it was never properly cleaned up, remaining as a vestigal argument
| Link_Funcs.append(link_dict[func]) | ||
|
|
||
| def LinkFunc(target, source, env) -> int: | ||
| def LinkFunc(target: list[Base], source: list[Base], env: Environment) -> int: |
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.
isn't Base imported above as Environment ?
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.
It is! This instead refers to the Node subclass of the same name that acts as the common ancestor for Entry/File/Dir
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.
Cue old grumble of mine: multiple clasess of the same name (and especially when it's a non-descriptive name like Base) just lead to confusion... I have gotten rid of a could of those...
SCons/Node/FS.py
Outdated
| self._path = None | ||
| self._tpath = None | ||
| self._path_elements = None | ||
| # FIXME: Declared as resolved types for hinting purposes, but do we need |
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've been using TODO: and not FIXME: for such
I think we need to keep setting to None as this is an abstract base class so if someone implemented a child of this without setting this (and the others) properly, it should break..
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.
Ahh, I see. I wonder if there's a more elegant way to ensure a variable is declared in a subclass... Something for another PR in any 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.
It's not completely an abstract base class, is it - as the comment says, it's "generic", but is actually used in some cases (and has the rather grotty thing where it morphs into soemthing else? If it was a true ABC, you can turn the attribute into a property with @property and then decorate it with @abstractmethod. That doesn't seem to align well with this case.
If it's really important to catch this case programmatically (rather than via checkers, or just via comments), you can make a __new__ at the top level that includes a check. I doubt whether that's really worth it, but something like:
class Base(SCons.Node.Node):
...
def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_path'):
raise NotImplementedError("Node classes must implement '_path')
return super().__new__(cls)|
Interesting the sphinx build broke. @mwichmann see anything in this PR which would reasonably impact sphinx? |
SCons/Node/Python.py
Outdated
| ###TODO: something reasonable about universal newlines | ||
| contents = str(self.value) | ||
| for kid in self.children(None): | ||
| for kid in self.children(False): |
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.
Just so it gets a vote, I've been making this change, slowly, in places where it makes sense (which means @bdbaddog has approved some of them ;) ): (a) if it's really a bool, where we only actually care about truthiness, don't use None as the false value, actually use False. (b) for strings, if an empty string is good enough to indicate "not set", then use that, instead of None.
In this case I'd actually use the kwarg: ...in self.children(scan=False) to be more clear (yeah, it's only a test...)
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.
Oh, that simplifies quite a few places then! I'll apply those where relevant here as well 👍
f581cb9 to
73935e4
Compare
it's the same thing it's been complaining about since we started to use sphinx, it's just not been fatal... the funky |
FWIW, I think it makes Sphinx happier if you combine Note that Sphinx 9.0.0 just dropped - yesterday (already a 9.0.1 from today), it's not unusual that something we used to be able to ignore becomes more serious in a new "major" release. I see in the test log it was indeed picking that one up: This is a snip from an api docs build on an earlier sphinx version - you can see the error is there, it just didn't abort: Now we've apparently had that bubble through instead of being caught: |
I was wrong on both counts. There is one reference to |
We don't know what qualname is here or where it comes from, and I don't know how to get a string's |
|
@mwichmann - we should probably file a bug against sphinx. I did a little digging with some LLM help on this. It's definitely in the napoleon plugin which is now part of the regular sphinx github repo. |
Belated followup to #4650.
As discussed in the original PR, this isn't aiming to be a full implementation, as the full ramifications of typehinting everything are well beyond the scope of this PR. This instead finishes the job the above PR started: defining the core Node types in a controlled environment.
Contributor Checklist:
CHANGES.txtandRELEASE.txt(and read theREADME.rst).