I agree that this may not be the case right now, but think whether an argument is modified in place is conceptually an important part of all of those subtask signatures (even if it’s not obvious in Python code), and that means the parent task ought to be able to know this. I think this is something we need to start paying more attention to.
I’m skeptical that we can rely on documentation to enforce const. That has not worked to date, and are well into the project. Also, it is very fragile. Suppose we have a top-level task A that calls B and calls C, none of which modify their exposure. Now a user retargets C with Cprime, but it does modify the exposure. Suddenly we have undefined behavior. This makes me really nervous. I think it would be safer if the system assumed the worst, and you had to go out of your way to get any other behavior.
Tasks are going to have to start declaring more of their behavior (including use of dataset types or use of multiple threads, for example). Declaring that they modify an input is not unreasonable. The declaration would use a mechanism that is visible without even instantiating the Task.
Is there a reasonable way to make all cached objects immutable? e.g. would it work & be acceptable to monkey patch the __setattr__
method to raise an exception if called?
At the same time maybe we could add a method to the object to get a copy of the object that the script would like to mutate (provided that the object is copyable).
Monkey patching __setattr__
wouldn’t work, and I’m skeptical in general, but it’s not entirely out of the question. The really big concern here is images (tables too, but it’s essentially the same problem for those). It’s fairly critical that we provide views (via NumPy) into those into those objects, which makes it essentially impossible to intercept modifications - unless we can sometimes provide read-only views and sometimes provide read-write views (which NumPy does support). That’s entirely natural in C++, since “constness” is a fundamental part of the language, and there’s generally no extra work to define a const version of a class. But it’s much less natural in Python, where (while it sometimes exists as in set
and frozenset
) it’s a lot of work to provide both mutable and immutable versions of everything.
I know something like this is intended for SuperTask, but was not aware we would be adding it to all tasks. It may help to have a programmatic way of querying this info, but without enforcement I’m still concerned.