Discussion:
[Bf-python] The road to deprecation
Sybren A. Stüvel
2014-12-20 11:18:52 UTC
Permalink
Hi folks,

Is there any way, at the moment, to deprecate parts of the Python API? I've
always been a fan of the following:

1. Method calls, property access etc. can be annotated as "deprecated".
2. In version N, we start displaying a warning when deprecated functionality
is used. This warning also mentions version N+1 as the version in which
it will stop working.
3. In version N+1, turn the warning into an error.
4. In version N+2, remove the functionality altogether.

How N, N+1 and N+2 map to Blender versions is another discussion. I'm just
wondering whether such a system exists in Blender, and if not, if people would
find it interesting.

The "root cause" for this, is the Scene.frame_current property. It's currently
writable, but its documentation tells you to call Scene.set_frame() instead.
This made me think about deprecating writing to Scene.frame_current, hence
this email.

Best,
--
Sybren A. Stüvel

http://stuvelfoto.nl/
http://stuvel.eu/
Bassam Kurdali
2014-12-20 18:16:19 UTC
Permalink
+1 for a formal way to deprecate api - this method would be good.

About Scene.frame_current - It's less useful than set_frame() because
the latter actually updates the scene to the new frame, but maybe there
are use cases where you just want to write to the property without (yet)
forcing an update? (though I'm not sure when or why you would want
that.)

I think getting a warning when the api writes to frame_current could be
a nice thing even if not deprecated, because most people actually want
to update the frame, not just write the property.
Post by Sybren A. Stüvel
Hi folks,
Is there any way, at the moment, to deprecate parts of the Python API? I've
1. Method calls, property access etc. can be annotated as "deprecated".
2. In version N, we start displaying a warning when deprecated functionality
is used. This warning also mentions version N+1 as the version in which
it will stop working.
3. In version N+1, turn the warning into an error.
4. In version N+2, remove the functionality altogether.
How N, N+1 and N+2 map to Blender versions is another discussion. I'm just
wondering whether such a system exists in Blender, and if not, if people would
find it interesting.
The "root cause" for this, is the Scene.frame_current property. It's currently
writable, but its documentation tells you to call Scene.set_frame() instead.
This made me think about deprecating writing to Scene.frame_current, hence
this email.
Best,
_______________________________________________
Bf-python mailing list
http://lists.blender.org/mailman/listinfo/bf-python
Sybren A. Stüvel
2014-12-22 15:56:04 UTC
Permalink
Post by Bassam Kurdali
+1 for a formal way to deprecate api - this method would be good.
That's great. I'm fairly sure that with the help of a few well-placed
#defines, this shouldn't be too hard to set up.
Post by Bassam Kurdali
I think getting a warning when the api writes to frame_current could
be a nice thing even if not deprecated, because most people actually
want to update the frame, not just write the property.
IMO a warning would be out of place is such a case. Either there is a
good use for writing to frame_current, and there should be no warning
(at least not at runtime), or there is not a good use case for it and
it should be deprecated.

An animation importer could have a use for writing to frame_current.
Since it only imports data, it may be independent of the already
existing data, hence a full scene update is not needed. Personally, I
think this would be a good enough use case to not deprecate writing to
frame_current. I'll see if I can update the documentation to clarify
this a bit more.
--
Sybren A. Stüvel

http://stuvelfoto.nl/
http://stuvel.eu/
Daniel Monteiro Basso
2014-12-22 16:38:00 UTC
Permalink
Post by Sybren A. Stüvel
An animation importer could have a use for writing to frame_current.
Since it only imports data, it may be independent of the already
existing data, hence a full scene update is not needed.
Scene.set_frame(x, update=False)
Post by Sybren A. Stüvel
Personally, I think this would be a good enough use case to not deprecate
writing to
frame_current.
- Explicit is better than implicit.
- Special cases aren't special enough to break the rules.
- In the face of ambiguity, refuse the temptation to guess.
- There should be one-- and preferably only one --obvious way to do it.

So I wholeheartedly agree with deprecating frame_current and incorporating
its behavior into set_frame.

Cheers,
Daniel
Campbell Barton
2015-01-06 03:42:42 UTC
Permalink
This thread covers a few issues, but I think it misses a more general problem.

For scripting you may want to separate assignment from its typical
side-effects (that you'd expect as a user).

Often its related to performance - so you can batch edits and postpone
re-evaluating data until they're all done.

But you may wan't to keep the old state in some cases too.

As a user, if you set the filepath of an image (for example), you
normally want it to load that image.

But when scripting, you may want to set an image path so it will
un-pack to that location... or so saving will write a newly-generated
image to that path. (This is a problem, and why we have 2x attributes
`filepath, filepath_raw` for images, which isn't very good design
either).

For `frame_current` the examples where you might take advantage of the
current behavior are less obvious.

Setting keyframes for the current object's state at 2 or more
different points in time. Basically any operation where you want to
change the frame and write-state, rather than reading it.

There are so many cases where you _might_ want an update that I think
its better to be explicit here.

For example, if you set a vertex location you don't get the result in
Python (updated bounding box etc) until you run `scene.update()`.
But it doesn't make sense to add a vertex.set_co() method just to get
an instant update. (wouldn't have to be added for every other data
type... uv's etc).


Why not instead remove `frame_set` and have an explicit update function?

::
scene.frame_current = 123
scene.frame_update()

Then we keep the rule of thumb that expensive global re-evaluation is
done explicitly.


On Tue, Dec 23, 2014 at 3:38 AM, Daniel Monteiro Basso
Post by Daniel Monteiro Basso
Post by Sybren A. Stüvel
An animation importer could have a use for writing to frame_current.
Since it only imports data, it may be independent of the already
existing data, hence a full scene update is not needed.
Scene.set_frame(x, update=False)
Post by Sybren A. Stüvel
Personally, I think this would be a good enough use case to not deprecate
writing to
frame_current.
- Explicit is better than implicit.
- Special cases aren't special enough to break the rules.
- In the face of ambiguity, refuse the temptation to guess.
- There should be one-- and preferably only one --obvious way to do it.
So I wholeheartedly agree with deprecating frame_current and incorporating
its behavior into set_frame.
Cheers,
Daniel
_______________________________________________
Bf-python mailing list
http://lists.blender.org/mailman/listinfo/bf-python
--
- Campbell
Sybren A. Stüvel
2015-01-06 15:35:08 UTC
Permalink
Post by Campbell Barton
There are so many cases where you _might_ want an update that I
think its better to be explicit here.
I fully agree.
Post by Campbell Barton
For example, if you set a vertex location you don't get the result
in Python (updated bounding box etc) until you run `scene.update()`.
But it doesn't make sense to add a vertex.set_co() method just to
get an instant update. (wouldn't have to be added for every other
data type... uv's etc).
Why not instead remove `frame_set` and have an explicit update
function?
scene.frame_current = 123
scene.frame_update()
Then we keep the rule of thumb that expensive global re-evaluation
is done explicitly.
That looks like a good plan.

Do you also agree with my 4-step deprecation idea?
--
Sybren A. Stüvel

http://stuvelfoto.nl/
http://stuvel.eu/
Dan Eicher
2015-01-07 03:28:59 UTC
Permalink
Hi,

For example, if you set a vertex location you don't get the result in
Post by Campbell Barton
Python (updated bounding box etc) until you run `scene.update()`.
But it doesn't make sense to add a vertex.set_co() method just to get
an instant update. (wouldn't have to be added for every other data
type... uv's etc).
Isn't one of the goals of the depsgraph refactor to make these expensive
updates more fine grained and fairly cheap?
Post by Campbell Barton
Why not instead remove `frame_set` and have an explicit update function?
I'd say just make scene.frame_current read-only (since it's really only
good for that anyway) and keep the current frame setting method so as to
not unnecessarily break any scripts.

That whole frame_current not updating has been there since the early 2.5
days and nobody has tried (and failed) to fix it other than myself so now
it's pretty much 'expected behavior' in who knows how many scripts.
Probably do more harm than good to mess with it now methinks.

Dan
Sybren A. Stüvel
2015-01-07 09:30:13 UTC
Permalink
Post by Campbell Barton
Post by Campbell Barton
For example, if you set a vertex location you don't get the result
in Python (updated bounding box etc) until you run
`scene.update()`. But it doesn't make sense to add a
vertex.set_co() method just to get an instant update. (wouldn't
have to be added for every other data type... uv's etc).
Isn't one of the goals of the depsgraph refactor to make these
expensive updates more fine grained and fairly cheap? 
That's true. However, no matter how good a programmer Sergey is, not
updating at all is still cheaper.
Post by Campbell Barton
Post by Campbell Barton
Why not instead remove `frame_set` and have an explicit update function?
I'd say just make scene.frame_current read-only (since it's really
only good for that anyway)
Writing to scene.frame_current still has its uses. For example, an
importer might only perform writing/setting actions. In that case it
doesn't need an updated scene, but may need to set the current frame
number.
Post by Campbell Barton
and keep the current frame setting method so as to not unnecessarily
break any scripts. 
This is exactly why I started this discussion. It would be nice to be
able to change functionality without breaking any scripts. Running a
script and checking the console for deprecation warnings is something
anyone can do, even people that do not know the script's source code.
This makes it easier to let scripts follow along with API changes.
--
Sybren A. Stüvel

http://stuvelfoto.nl/
http://stuvel.eu/
Sybren A. Stüvel
2015-01-11 13:01:32 UTC
Permalink
Hi all,
Post by Bassam Kurdali
+1 for a formal way to deprecate api - this method would be good.
Anyone interested, please take a look at
https://bitbucket.org/sybren/py-deprecation

I've created some C code that implements the proposed deprecation
process, including motivation, design, and some open design questions.
I'm curious as to your opinion on this.

Best,
--
Sybren A. Stüvel

http://stuvelfoto.nl/
http://stuvel.eu/
Loading...