-
Notifications
You must be signed in to change notification settings - Fork 36
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
Type annotations #75
base: master
Are you sure you want to change the base?
Type annotations #75
Conversation
Nice one.
This is interesting, because in your screenshot, it shows you the PEP8 versions of the name. Those are technically aliases, and not the actual names of the class, which are mixedCase, like the Maya API. I personally only use the snake_case names in my code, but it's not trivial to make those the only names, since a lot of the classes are subclasses that inherit their mixedCase names. So, I wonder if the auto-complete shows both versions? 🤔 Should it?
This is "metadata". A transient dictionary you can use to attach data that persists with the node, but isn't saved with the scene.
What is an actual abstract class? 🤔 |
It's actually showing both, the camelCase one was just lower down the completion cause it was sorted alphabetically.
I'm fine with showing both, at least for now
An abstract class is a class that can't be instantiated directly and has to be inherited from. They mostly serve as defining a common interface that all subclasses must implement from abc import ABC, abstractmethod
class Attribute(ABC):
@abstractmethod
def read(self, data):
pass
class Double(Attribute):
def read(self, data):
return 1.0
# This works:
attr = Double()
# But this fails:
# TypeError: Can't instantiate abstract class Attribute with abstract methods read
attr = Attribute() Speaking of attributes:
# This snippets contains stubs for creating attributes only, not setting them.
class Node:
# Ideal type annotation
def __setitem__(self, key: str, value: _AbstractAttribute) -> None: ...
# current type annotation
def __setitem__(self, key: str, value: Tuple[Type[_AbstractAttribute], Dict[str, Any]) -> None: ... I am absolutely not expecting you to agree with all my suggestions btw, I fully appreciate that some of the changes I'm going to suggest are going to turn out to radical to actually be implemented haha |
Ok, sounds reasonable.
Ok, but why? What is it about the
That's exactly it. It's not much used, at least I don't use it. Because it doesn't jive with undo/redo. So if it's a problem, we could probably deprecate that convenience. Initially it came from the earliest version of cmdx, where there was no classes, only a plain dictionaries of plain data. I liked the simplicity of that, but needed a method or two attached to it, until eventually it became the mostly-class-looking thing that it is today. |
My thought process was:
This is not needed right, it just feels cleaner to me
Ahh I gotcha, you use Out of curiosity, do you have a strategy for deprecating features or do you just remove things? |
Is this something visual? Something in your IDE? I'm trying to figure out what's weird about it, I had almost forgotten it even existed as it's just a baseclass. It's private with an underscore to highlight that you aren't meant to instantiate it which I don't expect anyone would even try. We could make it "abstract" and prevent instantiation further, but I just don't see what it would change? I'm inclined to keep things as they are, unless you can convince me this isn't just bikeshedding. :)
Actually not even that, because that is also not undoable. My use is primarily interactive, so the modifiers are the way to go. with cmdx.DagModifier() as mod:
node = mod.create_node("transform")
mod.add_attr(node, cmdx.Double("attrName", default=1.0)) For plug-ins, that's a different story and was the original usecase for cmdx, for which the former syntax is the most readable I think. node["someDouble"] = cmdx.Double(default=1)
node["someLong"] = cmdx.Long()
Nothing is removed and there is no deprecation. We can nudge and recommend alternatives, but backwards compatibility is of utmost importance. Anything removed must have an equivalent wrapper or alias to the same name and arguments. Think of how software written for Windows 95 still works on Windows 11 and you get the idea. :) |
I've started working on making type stubs for cmdx.
I ended up going the stubs way as I used a few features that wouldn't work in python 2 without the typing and typing-extensions libraries.
I've only added two commits so far, the first one is the raw stubs from stubgen, not too interesting
Have a look at the 2nd one to see what I did exactly.
most things should be pretty self explanatory but a few nice QoL improvements are already standing out, even if you're not into static typing:
Node.__getitem__
returns a plug so you can have nice completion and all that when retrieving a plug@overload
decorators on a couple methods likeNode.connections
which let me assign different return types to different arguments.In this case based on the
plugs
andconnections
arguments, we get different return types and your editor is aware of thatCouple questions:
Node.data()
ever used anywhere? it seems to access_data
which is never set_AbstractAttribute
toAttribute
and making it an actual abstract class be ok with you?It feels weird to include it in the signature of the public API considering that it's currently private