Versioning Practices & Guarantees ================================= This page explains what you can expect when upgrading mcstatus, and what changes may occur in major, minor, and patch releases. mcstatus follows the `Semantic Versioning `_ model in terms of **versioning guarantees and expectations**, using the familiar ``MAJOR.MINOR.PATCH`` structure. Internally and for distribution, mcstatus version numbers follow `PEP 440 `_. This primarily affects the exact format of pre-releases, post-releases, and development releases, but does not change the meaning of major, minor, or patch version increments. - **MAJOR**: incompatible (breaking) changes to the public API - **MINOR**: backwards-compatible features and improvements - **PATCH**: backwards-compatible bug fixes What is "public API"? --------------------- For mcstatus, the **public API** is defined by what is **documented in the public API pages**. - Anything documented under :doc:`/api/basic` and :doc:`/api/motd_parsing` is public API. - Anything documented under :doc:`/api/internal` is **not** public API. - Anything not documented at all is also **not** public API. - Any module, package, attribute, or symbol whose name starts with an underscore (``_``) is considered internal and may change at any time. Release types and guarantees ---------------------------- .. warning:: **Bug fixes are generally not backported.** mcstatus primarily supports the **latest released version** of the library. Bugs are fixed only in that version, and fixes are not backported to older releases. This includes most bug fixes and the vast majority of security-related fixes. Backporting fixes significantly increases maintenance overhead and often requires maintaining multiple diverging code paths, which is not sustainable for this project. In exceptional cases, a truly critical issue may be addressed via a hotfix release. Such cases are rare and handled on a best-effort basis. If you rely on older versions of mcstatus, you may encounter bugs that will not be fixed unless you upgrade. Patch releases (x.y.PATCH) ~~~~~~~~~~~~~~~~~~~~~~~~~~ Patch releases contain: - bug fixes - documentation changes of any kind (e.g. new docs pages, or also changes to docstrings of some public API objects in the codebase) - improvements that do not change the public API contract - breaking changes in private API - dependency updates (including major dependency updates), as long as the public contract of this library remains compatible - changes in library's public API typing behavior (see :ref:`typing-stability-guarantees`) Patch releases do **not** contain breaking changes to the public API. They also generally don't introduce any new behavior, other than for purposes of resolving existing bugs, or internal updates. Note that in some cases, if you are relying on behavior which we consider to be a bug, it is possible that we might end up changing this behavior in a `PATCH` release, in an effort to fix the unintentional, wrong behavior, breaking your dependency. Bug-fixes pretty much always happen without any deprecations. .. admonition:: Example To understand what constitutes a bug-fix with such breakage potential, as an example, if mcstatus incorrectly parses a MOTD format that some server sends, fixing that parsing is a bug fix, even if it changes the output format for that specific broken MOTD. Another important note to mention is that mcstatus will not make any efforts to delay its runtime dependency version updates to align them with minor or major releases. Transitive breakages caused by dependency updates are considered acceptable as long as mcstatus's documented public API remains compatible. Minor releases (x.MINOR.z) ~~~~~~~~~~~~~~~~~~~~~~~~~~ Generally, minor releases exist to introduce new features to the library in a non-breaking way. They may include: - new public features (new classes, functions, parameters, constants) without affecting existing behavior - new optional arguments in public functions/class constructors with sensible defaults that don't change existing usage - **new deprecations** (introduced as warnings containing new replacements / deprecation reasons) - backwards-compatible behavior improvements - dropping support for a Python version (e.g. dropping Python 3.9 because it is past its `end-of-life `_) - any additional changes that patch releases can contain Minor releases do **not** intentionally introduce breaking changes to the documented public API. Deprecations in minor releases ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ New deprecations may be introduced in minor releases for behavior that is scheduled for removal in the next major version. These deprecations are emitted as warnings and do not immediately break existing code. For more information about our deprecation handling, see the :ref:`deprecations-and-removals` section. Major releases (MAJOR.y.z) ~~~~~~~~~~~~~~~~~~~~~~~~~~ Major releases may include breaking changes to the documented public API. These will be called out in the changelog and typically include one or more of: - removing a documented public class, function, or attribute - renaming a public API without a deprecated alias - changing the default value or meaning of a function parameter in a way that changes original usage - removing a deprecated alias or deprecated import path - any additional changes that minor and patch releases can contain We generally try to avoid immediate breaking changes that didn't go through at least a brief deprecation period of at least 1 release cycle (e.g. deprecation will first be introduced in v12.4.0, before the old behavior is removed in v13). If a major refactor of the library was performed, or just generally one that is expected to make a lot of our users to face deprecations, we try to introduce these deprecations in a major release, instead of a minor one (with them staying in the project until the next major release after this one). Though this is not a guarantee. We can still choose to not go through deprecations at all and introduce entirely new breaking changes in a new major release. We will however try to avoid doing so unless we have a very strong reason to do so. mcstatus and Minecraft versions ------------------------------- mcstatus is somewhat coupled to Minecraft server protocols and behaviors. As Minecraft evolves, mcstatus may need to make changes that are "breaking" at the library level, even if they are driven by protocol or ecosystem changes. mcstatus aims to: - remain compatible with widely used Minecraft versions and server implementations - release updates in a timely manner when protocol behavior or common server responses change - provide support for legacy Minecraft versions (within reason), if the latest protocol for obtaining status is no longer compatible with the previous one Fortunately, breaking changes in the protocol when it comes to obtaining server status are very uncommon. But it is possible that Minecraft introduces a change that our library cannot process at the time of introduction, this might or might not cause hard failures on mcstatus part, even if older Minecraft clients can process these information, mcstatus might not be able to, until we release a new version to support it. Because mcstatus is maintained by volunteers, timing may vary, but we try to keep mcstatus working with the latest Minecraft releases and fix critical bugs quickly. .. _typing-stability-guarantees: Typing stability guarantees --------------------------- mcstatus is a strongly typed library which actively supports and encourages the use of type-checkers. However, typing definitions occasionally need to change alongside internal refactors so that mcstatus itself remains internally type-correct, and Python's typing system unfortunately does not really provide a practical way to deprecate types gracefully. For this reason, **typing breakages may occur even in patch releases**. We actively try to avoid typing breakages or postpone them to minor or even major releases when possible, but if doing so would significantly slow down our ability to deliver a necessary bug-fix or feature, we do not consider maintaining the stability of the public typing interface significant enough to prevent us from shipping such a change. .. admonition:: Example To understand what we meant by breaking changes in the public typing interface, it can include things like: - Adding a ``@final`` decorator to one of our classes - Making a class generic - Introducing an additional type parameter to already generic class - Removing a generic type parameter / making a class no longer generic - Adding a convenience type-alias variable - Adding a new type into a union of types in an exposed convenience type-alias Any of these changes can occur even in a patch release. .. _deprecations-and-removals: Deprecations and removals ------------------------- When we deprecate something, we aim to emit a ``DeprecationWarning`` with a message containing: - what was deprecated - what to use instead (if a replacement is available) - a target removal version When we deprecate something, we generally aim to remove it in a **major release**, after it has been deprecated for at least one release cycle. (E.g. a deprecation introduced in ``v12.2.0`` will most likely have its removal scheduled in ``v13.0.0`` ). For some more significant changes, we can sometimes keep a deprecation around for longer though (e.g. a deprecation introduced in ``v12.2.0`` with removal scheduled for ``v14.0.0``). We will **always** explicitly include the removal version, until which the deprecated behavior will still be guaranteed to remain functional. Post-removal deprecation handling ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Once a deprecated feature has passed its stated removal version, its use will result in a breaking change. This is guaranteed to happen in the stated removal version. .. warning:: **Relying on deprecated behavior after its removal is unsupported.** Where feasible, mcstatus will explicitly raise the corresponding ``DeprecationWarning`` as a hard exception, rather than allowing the removal to manifest as a less clear runtime failures (such as ``AttributeError``). This is a deliberate best-effort attempt to provide clearer diagnostics and improve the upgrade experience. This behavior is **not part of the versioning guarantees**. Any post-removal deprecation handling is considered **temporary by design** and may be intentionally removed after some time, including in patch releases, once the breakage has been in effect for a reasonable period (typically 1-5 months). Users must not rely on the presence, wording, or longevity of post-removal deprecation handling. After removal, failures may surface as generic runtime errors without any direct reference to the original deprecation. For this reason, you should always pay attention to deprecation warnings and resolve them ahead of time, ideally after any minor updates, but at the very least before upgrading to a new major version, to avoid unclear hard breakages.