Skip to content

Conversation

@EwoutH
Copy link
Member

@EwoutH EwoutH commented Nov 29, 2025

Summary

Adds a new "Deprecation Policy" section to our contributor guide, establishing clear guidelines for how we deprecate features in Mesa.

Motive

As discussed in #1909 and various PR reviews (e.g., #2841 and #2872), we've been making ad-hoc decisions about deprecation practices. This has led to repeated discussions about which warning type to use, when deprecations can be added, and what prerequisites are needed. Having a documented policy will streamline future PRs and ensure consistent user experience.\

Please review critically:

  • if you agree with the deprecation policy as described
  • if it's clear what needs to be done to deprecate a feature (so if it's a good reference)

@EwoutH EwoutH added the docs Release notes label label Nov 29, 2025
Copy link
Member

@tpike3 tpike3 left a comment

Choose a reason for hiding this comment

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

LGTM

@jackiekazil
Copy link
Member

jackiekazil commented Nov 29, 2025

LGTM - thank you for adding this.

@Sahil-Chhoker
Copy link
Collaborator

I'm a little confused, like in #2893 I've changed the code and examples but the migration guide and tutorials remain as is, following this document I should also update the docs and migration guide but then won't the users be unable to see the API before it was changed and won't be able to follow the tutorials.

I was thinking of updating the tutorials and migration guide once the change will be changed to DeprecationWarning from PendingDeprecationWarning.

@EwoutH
Copy link
Member Author

EwoutH commented Nov 30, 2025

Great question! The prerequisites don’t all need to happen at once, they can be done anywhere between adding the alternative and the final deprecation. Notice the difference between may and must in the policy. The key is that everything is in place before/when we add the DeprecationWarning.

So your approach in #2893 is fine: add the alternative with a PendingDeprecationWarning, then update docs/tutorials/migration guide in follow-up PRs before/when switching to DeprecationWarning.

Regarding visibility of the old API: these changes are to our main branch, but tagged releases and their docs remain available. Users on older versions can always access the corresponding documentation.

@quaquel
Copy link
Member

quaquel commented Dec 1, 2025

Just one clarifying question: why use PendingDeprecationWarning and DeprecationWarning instead of using FutureWarning?

@EwoutH
Copy link
Member Author

EwoutH commented Dec 1, 2025

@quaquel This is actually an interesting question. I looked into this and the distinction comes down to intended audience:

  • DeprecationWarning/PendingDeprecationWarning: For developers, hidden by default
  • FutureWarning: For end users, shown by default

For Mesa, our users actively write code against our API: they subclass Model and Agent, call our methods directly. They're the developers who need to update their code, and they can act on warnings.

So it depends a bit if you see them as end-users or developers. They're probably both.

Libraries with similar dynamics (NumPy, pandas, scikit-learn) use FutureWarning for public API changes for this reason. With the current two-stage approach, users running their models normally would never see any warning unless they explicitly enable them or run pytest.

While DeprecationWarning is shown for code in __main__, this doesn't really help for library deprecations. The deprecated methods live in Mesa's modules, not in the user's script, so even a single-file model triggers warnings from imported code. The __main__ exception essentially never applies here.

I would like to check this though, because I do remember having seen DeprecationWarnings here and there when building models.

But I think we should indeed update to FutureWarning for public API changes. Learned something today!

@EwoutH
Copy link
Member Author

EwoutH commented Dec 1, 2025

pandas has a whole spec around this: PDEP-17. They start with DeprecationWarning, then switch to FutureWarning in the last minor release before removal. This gives library maintainers early warning (via pytest/CI) while ensuring end users see it before it breaks.

We could adopt a similar pattern: DeprecationWarning for initial deprecation, switching to FutureWarning one release before removal (or one minor release after the replacement is fully available).

@quaquel
Copy link
Member

quaquel commented Dec 1, 2025

So it depends a bit if you see them as end-users or developers. They're probably both.

This is something I have been struggling with myself as well. I see them more as end-users, but technically they are developers since they use our library in their own code.

While DeprecationWarning is shown for code in main, this doesn't really help for library deprecations. The deprecated methods live in Mesa's modules, not in the user's script, so even a single-file model triggers warnings from imported code. The main exception essentially never applies here.

If you run your own custom mesa model from within main, as any sane person should do, you'll get your deprecation warnings wherever we put them. What matters is just that you call mesa stuff that raises a deprecation warning directly or indirectly from a main.

We could adopt a similar pattern: DeprecationWarning for initial deprecation, switching to FutureWarning one release before removal (or one minor release after the replacement is fully available).

I agree that this is the best approach going forward.

Restructures the deprecation policy around a clear 4-step process:
(1) introduce alternative with optional PendingDeprecationWarning
(2) complete prerequisites (docs, migration guide, examples)
(3) add FutureWarning for active deprecation
(4) remove in next major version.

Changes the active deprecation warning from DeprecationWarning to FutureWarning, which is visible to users by default. This is important since Mesa's deprecated methods live in imported modules, not user scripts, so DeprecationWarning would be hidden even when users run code in __main__.
@EwoutH
Copy link
Member Author

EwoutH commented Dec 1, 2025

I validated the behavior above, it's correctly described.

I also thought about it a bit more, and DeprecationWarning is the most unpredictable: If they pop-up depends on how you structure your code. So let's not use them, and let's only use PendingDeprecationWarning (as placeholder) and FutureWarning.

I rewrote the guide to reflect that, and also made the order a bit more clear (it's now 4 logical steps).

Please rereview.

@EwoutH
Copy link
Member Author

EwoutH commented Dec 3, 2025

Merging, future additions/changes can be made later.

@EwoutH EwoutH merged commit 62889b5 into main Dec 3, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Release notes label

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants