Skip to content
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

SymPEP Purpose and Process and SymPEP Template #2

Merged
merged 16 commits into from
Sep 18, 2023
270 changes: 270 additions & 0 deletions SymPEP-0001.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
# SymPEP 1 --- SymPEP Purpose and Process

**Author** Aaron Meurer, Jason K. Moore
**Status** Draft
moorepants marked this conversation as resolved.
Show resolved Hide resolved
**Type** Process
**Created** 2021-01-27
**Resolution**

## Abstract

SymPEPs are a formal process whereby important changes are proposed and
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
SymPEPs are a formal process whereby important changes are proposed and
SymPEPs are a formal process whereby important controversial changes are proposed and

I just read this "Matplotlib Enhancement Proposals (MEP), inspired by cpython's PEP's but less formal, are design documents for large or controversial changes to Matplotilb." and liked the word "controversial". This may help people defer to a normal PR or mailing list discussion before coming to make a SYMPEP.

Copy link
Member Author

Choose a reason for hiding this comment

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

I think this is the most significant point that's missing here, and it really deserves more text than just a single word. It isn't clear just what sorts of changes require a SymPEP and which changes can just be an issue or PR. I really think the default should be to not have a SymPEP, at least for codebase changes (process/governance changes are different). This isn't CPython. We don't need a proposal just to add or change anything.

Actually I'm not sure "controversial" is the right word to use here. A very big change may be uncontroversial, at least in principle, but still require a SymPEP because it requires a lot of coordination, or because we need to get everyone on the same page with the details.

Of course, controversial things should be discussed as well, but I'm a little unclear what that means. If something is controversial, shouldn't it just be rejected, because that's by definition a lack of community consensus.

discussed. Corresponding to each SymPEP is a document that outlines the
proposed change(s), the discussion around those changes, and motivation for
that change. This document outlines the details of the SymPEP process and
corresponding documents.

## What is a SymPEP?

SymPEP stands for "SymPy Enhancement Proposal". SymPEPs represent a formal
process whereby important changes are proposed and discussed in the SymPy
community. Corresponding to each SymPEP is a SymPEP document which outlines the
proposal and corresponding discussion. SymPEPs are based on the
[PEP](https://www.python.org/dev/peps/) process used by the Python language
community to propose changes to the Python language. It also takes motivations
from other similar processes in communities adjacent to SymPy, such as the
[NEP](https://numpy.org/neps/nep-0000.html) process for NumPy and the
[MEP](https://matplotlib.org/devel/MEP/index.html) process for Matplotlib.
However, the SymPEP process differs from these processes in some ways, so those
who may already be familiar with similar processes from other communities
should read this document to understand how it works for SymPEPs.

## Types

There are two kinds of SymPEPs:

A **Software Track** SymPEP describes a new feature or important change for the
code in SymPy.

A **Process** SymPEP describes a process related to SymPy, or proposes a
change to (or an event in) a process. Process SymPEPs are like Software Track
SymPEPs but apply to areas other than the SymPy library itself. They may
propose an implementation, but not to SymPy’s codebase; they require community
consensus. Examples include procedures, guidelines, changes to the
decision-making process, and changes to the tools or environment used in SymPy
development. Any meta-SymPEP is also considered a Process SymPEP.

## Purpose

The SymPEP process and corresponding documents serve several purposes:

- To decide, as a community, whether a proposed change should be made.
- To decide on the process by which a change will be implemented, for example,
whether the change should be implemented in several stages, whether
intermediate releases are required for things like deprecations, and so on.
- To document the above discussions and decisions for future reference.
- To document the motivations for a change from the perspective of end users
who may be affected by it. Here "end users" means both users of the SymPy
library, developers working on parts of SymPy itself which may be affected by
the change, and developers of downstream libraries that depend on SymPy.

Importantly, **a SymPEP is not documentation** for the proposed change. End
user documentation should be included with the implementation of the feature in
the corresponding SymPy documentation. This also means that other documentation
should not rely on cross-referencing a SymPEP as if it were documentation for a
feature. Even technical discussion of a feature should be documented separately
from a SymPEP. The reason is that SymPEPs will necessarily include details that
are irrelevant to the final implementation, such as discussions of alternate
implementations which were rejected and discussions of implementation of the
change.

## SymPEP Workflow

Discussions around a proposed change typically begin informally on the mailing
list or SymPy issue/pull-request tracker. However, once it is decided that the
formal SymPEP process is desired for a change, the discussion should move to
the [SymPEP repository](https://github.com/sympy/SymPEPs) on GitHub.

Not all significant changes or additions to SymPy require a SymPEP. If the
change would benefit from extended discussion or needs a roadmap for
implementation, a SymPEP should be considered. If unsure, consult with the
community on the currently active discussion forum. Most changes to and
decisions regarding SymPy can be made through issues and pull requests, so it
is best to start with one or the other. Examples of things that likely need a
SymPEP are: major version changes (1.X.X -> 2.0), large breaks in backwards
compatibility, adding new primary packages within SymPy, adding hard
dependencies, introduction of development practices or tools all developers
need to adopt, etc. Long term SymPy policies and goals should also be discussed
and developed as SymPEPs. Statements of these policies and goals should be
incorporated into the SymPy documentation, as determined in the associated
SymPEP.

Every SymPEP must have at least one champion. The champion(s) are persons who
are responsible for writing the SymPEP, leading the discussions around it, and
developing consensus around it.

The author of a SymPEP should fork the repository and create a draft pull
request with a new SymPEP document based on the [SymPEP
template](SymPEP-template). The SymPEP document may be named `SymPEP-XXXX.md`
until a number is assigned. Once the author completes all information in the
template and would like it to be reviewed, one of the [core SymPy
developers](https://github.com/orgs/sympy/teams/developers-with-push-access-to-everything)
should decide if the proposal is a legitimate proposal and then assign a number
to the SymPEP, in which case `XXXX` should be replaced with the number with
leading 0s. The pull request can then be moved to an open pull request and is
ready for community feedback and discussion but remains in draft status. The
person who assigns the number should also update the
[README](https://github.com/sympy/SymPEPs/blob/main/README.md) of the main
[SymPEP repository](https://github.com/sympy/SymPEPs) to list that number.
Numbers should be assigned to SymPEPs as soon as it is determined that they are
a legitimate proposal. If a SymPEP is not deemed necessary, the author should
rework the SymPEP or move it to a normal pull request or issue on the main
SymPy repository. If a SymPEP ends up being rejected or postponed, it keeps its
number, as rejection or postponement status is still a discussion that should
be documented in the SymPEP. SymPEP numbers should generally be assigned in
increasing numeric order.

The author should announce the SymPEP on the mailing list when the number is
assigned to encourage discussion. Discussion on the SymPEP should primarily
continue on the open pull request but may also take place in other places, such
as [GitHub discussions](https://github.com/sympy/SymPEPs/discussions) or the
[mailing list](http://groups.google.com/group/sympy) with the latter being
favored. All discussions should be cross-referenced in the "Discussions"
section of the SymPEP document.

For each SymPEP, the community should decide whether a draft implementation of
the change is needed before acceptance or not. For instance, if a SymPEP
concerns the details of how a feature is implemented, it should be accepted
before that happens. On the other hand, the community may decide that it cannot
come to a consensus about a SymPEP until a draft implementation is proposed.

Once the community reaches a consensus about a SymPEP, the status of a SymPEP
should be updated (see below). This consensus may be to accept or to reject
the SymPEP, or to defer it. Here the "community" refers to the broader
community that has a stake in the SymPEP, not just the core SymPy developers.
The purpose of the SymPEP process is not to create a cabal of decision makers,
but rather to enhance the involvement of the broader SymPy community in the
decision making process.
Comment on lines +131 to +137
Copy link
Contributor

Choose a reason for hiding this comment

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

Here "consensus" is a very tricky concept. Inherently the idea of working by strict consensus does not scale well up to large groups of people because it implies that any single person has a "veto". I often find this tricky on pull requests because often tangential comments might seem to give a negative opinion but it is not clear how strongly that negative opinion is felt.

Also consensus typically refers only to those who participate visibly in a discussion and often there will be others who do not understand the details of something but might still be affected by it.

I can see that the wording here is careful not to define the decision making process formally and perhaps it is better to keep it that way. I suggest softening the word consensus somehow to allow that it does not strictly require unanimous agreement. Perhaps "broad consensus" or "loose consensus" is better?

Copy link
Member

Choose a reason for hiding this comment

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

I've used "tacit consensus" in the past. But I think we actually do operate on a proper full consensus, but that the lead developer (Ondrej, then Aaron, and then now possibly you) could overrule a dissenting vote if full consensus can't actually be achieved.

Copy link
Member

Choose a reason for hiding this comment

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

Actually, I think it is best to leave it ambiguous. We have a culture of our method of consensus that is publicly visible. If someone attempts to use/push a different way of consensus that is different than we already do, then people will point to the prior approaches to show how things are done. Worst case is that the lead dev takes control and makes a decision outside of consensus.

Copy link
Member Author

Choose a reason for hiding this comment

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

I see the SymPEP process as basically a replacement for the BDFL style decision making we've had in the past (which hasn't really been necessary for a long time anyway). And if we really did want to formalize some sort of actual governance mechanism, that should be done itself through a SymPEP. But that should not be part of this SymPEP, which is just about the template and process for SymPEPs themselves.

Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure I see how this is a replacement. Given that we have not defined consensus in an explicit way, this can coexist with BDFL style (which is consensus with fallback on dictator if all else fails). I don't see merging this and accepting it as removing anything about the informal, yet existing, decision making process we already have.

Copy link
Member Author

Choose a reason for hiding this comment

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

Reading through this paragraph again, I agree with Jason. I intentionally left this ambiguous, because the alternative is to outline some rigorous decision making process, which implies some sort of governance which doesn't exist (or at least hasn't been decided on).

In fact, the main point I was trying to make with this paragraph is that a SymPEP should involve every relevant stakeholder, not just the core dev team (whatever that means). That also includes non-SymPy developers such as users of SymPy and downstream dependents.

I would use the term "clear consensus". If something isn't clearly agreed upon, then at best that means the default is to not accept, at least without some further decision making process which isn't defined here.


### Status

The **status** section at the top of the SymPEP document (see the
[template](SymPEP-template)) should be updated according to the current status
of the SymPEP. Do not confuse this with the "draft/open pull request state on
Github".

All SymPEPs should be created with the **Draft** status. **Draft** status
SymPEPs generally live in a pull request.

Eventually, after discussion, there may be a consensus that the SymPEP should
be accepted; see the next section for details. At this point the status becomes
**Accepted**.

Once a SymPEP has been **Accepted**, the reference implementation must be
completed. When the reference implementation is complete and incorporated into
the main source code repository, the status will be changed to **Final**.

A SymPEP can also be assigned status **Deferred**. The SymPEP author or a core
developer can assign the SymPEP this status when no progress is being made on
the SymPEP.

A SymPEP can also be **Rejected**. Perhaps after all is said and done it was
not a good idea. It is still important to have a record of this fact. The
**Withdrawn** status is similar, it means that the SymPEP author themselves has
decided that the SymPEP is actually a bad idea or has accepted that a competing
proposal is a better alternative.

SymPEPs can also be **Superseded** by a different SymPEP, rendering the
original obsolete.

Process SymPEPs may also have a status of **Active** if they are never meant to
be completed, e.g. SymPEP 1 (this SymPEP).

### Merging the SymPEP Document Pull Request

Whenever a SymPEP moves from the **Draft** status to one of the other above
statuses, the header should be updated, and the corresponding pull request
should be merged. This way the document lives inside of the SymPEP repository
proper. SymPEPs that are merged are not set in stone, and may be updated by
future pull requests (although SymPEPs that are **Accepted** should generally
not be significantly modified once they have reached that status). The purpose
of merging is simply to make the SymPEP visible in the repository, even if it
isn't yet accepted or rejected. SymPEP discussions that have stalled should
also be merged, so that the SymPEP becomes visible in the SymPEP repository
proper—again, discussion may be picked up again with a new pull request.
moorepants marked this conversation as resolved.
Show resolved Hide resolved

## Accepting a SymPEP
moorepants marked this conversation as resolved.
Show resolved Hide resolved

Once a SymPEP is Accepted by consensus of all interested contributors, an email
should be sent to the [SymPy mailing
list](http://groups.google.com/group/sympy) with a subject like:

Proposal to accept SymPEP #<number>: <title>

In the body of your email, you should:

- link to the latest version of the SymPEP,

- briefly describe any major points of contention and how they were resolved,

- include a sentence like: "If there are no substantive objections within 7
days from this email, then the SymPEP will be accepted; see SymPEP 1 for more
details."

After you send the email, add the email thread to the Discussion section of the
SymPEP, so that people can find it later.

Generally the SymPEP author will be the one to send this email, but anyone can
do it. The important thing is to make sure that everyone knows when a SymPEP is
on the verge of acceptance, and give them a final chance to respond. If there's
some special reason to extend this final comment period beyond 7 days, then
that's fine, just say so in the email. It shouldn't be less than 7 days,
because sometimes people are traveling or similar and need some time to
respond.
moorepants marked this conversation as resolved.
Show resolved Hide resolved

In general, the goal is to make sure that the community has consensus, not
provide a rigid policy for people to try to game. When in doubt, err on the
side of asking for more feedback and looking for opportunities to compromise.

It is also important that SymPEPs are a mechanism to enable change as opposed
to hindering and slowing change. The general approach of reviewers should be to
help the author get it to a state that can be accepted or by offering
alternative proposals. SymPEPs shouldn't be the place where energy and ideas
die.

If the final comment period passes without any substantive objections, then
the SymPEP can officially be marked **Accepted**. A followup email should then
be sent notifying the list. Update the SymPEP by setting its **Status** to
**Accepted**, and its **Resolution** header to a link to your followup email.
The SymPEP pull request should be merged at this time, if it hasn't been
already, so that it is visible in the SymPEP repository proper.

If there are substantive objections, then the SymPEP remains in Draft state,
discussion continues as normal, and it can be proposed for acceptance again
later once the objections are resolved.

## SymPEP Steps
moorepants marked this conversation as resolved.
Show resolved Hide resolved

This describes the general set of steps for a SymPEP:

- From a discussion in the mailing list, an issue or PR, someone might suggest
a SymPEP being needed.
- If discussion did not start on the mailing list, then move to the mailing
list (with cross-reference links) to gage whether a SymPEP is appropriate to
oscarbenjamin marked this conversation as resolved.
Show resolved Hide resolved
pursue.
- If it seems appropriate, make a draft pull request with your SymPEP. When your
draft is ready for a review, request a number assignment on the pull request.
- A core developer other than the author(s) assigns the number and opens the
pull request (out of Github draft state).
- Announce on the mailing list that the SymPEP is ready for review and
discussion. Suggest the primary forum for detailed discussion.
- Detailed discussion takes place in the designated forum until consensus of
those participating is reached.
- Once reached, announce the final draft of SymPEP on the mailing list and then
it can be 7 days or perhaps longer, if indicated, for anyone to object.
- After the objection period, the status of the SymPEP is set to "Accepted" and
a core developer merges the pull request.
- After implementation of the software changes or process changes, update the
SymPEP status to "Final".

Deferment, rejection, or deemed inappropriate steps may occur along the way.

## Discussion

- [Initial mailing list post proposing
SymPEPs](https://groups.google.com/forum/#!msg/sympy/5RVMiWuCjoA/lr64dS1BBAAJ)
- [sympy/SymPEPs#2](https://github.com/sympy/SymPEPs/pull/2)

## Copyright

This document has been placed in the public domain.
Loading