Politique de dépréciation#
De nombreux utilisateurs et les autres paquets dépendent de différentes parties de Qiskit. Nous devons veiller à ce que chaque fois que nous apportons des modifications au code, nous donnons aux utilisateurs le temps d’ajuster sans casser le code qu’ils ont déjà écrit.
Plus important : ne modifiez aucune interface publique à moins que ce soit absolument nécéssaire. Ajouter des choses ne pose pas de problème, mais en enlever est ennuyeux pour les utilisateurs, mais peut être géré raisonnablement avec beaucoup de préavis, le changement de comportement signifie généralement que les utilisateurs ne peuvent pas écrire de code qui fonctionnera avec deux versions ultérieures de Qiskit, ce qui n’est pas acceptable.
Soyez conscients du fait que les utilisateurs utiliseront souvent des fonctions, des classes et des méthodes que nous, les développeurs de Qiskit, pouvons considérer comme internes ou peu utilisées. Ne faites pas d’hypothèses selon lesquelles « ceci est enterré, donc personne ne l’utilisera » ; si un élément est public, il est soumis à la politique. Les seules exceptions ici sont les fonctions et les modules qui sont explicitement internes, i.e. ceux dont le nom commence par un underscore (_
).
Les principes directeurs sont les suivants:
nous ne devons pas supprimer ou modifier le code sans avertissement actif pendant au moins trois mois ou deux cycles de version complets ;
il doit toujours y avoir un moyen d’atteindre des objectifs valables qui n’émettent aucun avertissement;
ne suppose jamais qu’une fonction qui n’est pas explicitement interne n’est pas utilisée ;
toutes les dépréciations, les changements et les suppressions sont considérés comme des changements de l’API et ne peuvent se produire que dans des versions mineures et non des versions de correctifs, par :ref:` politique de branche stable <stable_branch_policy>`.
Suppression d’une fonctionnalité#
Lors de la suppression d’une fonctionnalité (par exemple une classe, une fonction ou un paramètre de fonction), nous suivrons cette procédure :
Le chemin alternatif doit être en place pour une version mineure avant que des avertissements ne soient émis. Par exemple, si nous voulons remplacer la fonction
foo()
par la fonctionbar()
, nous devons faire au moins une version avec les deux fonctions avant d’émettre des avertissements dansfoo()
. Vous pouvez émettre desPendingDeprecationWarning
dans les anciens chemins immédiatement.Raison : nous devons donner aux utilisateurs le temps d’adapter leur code pour le mettre à jour facilement lors des mise à niveau.
Une fois que le chemin alternatif a été en place pour au moins une version mineure, :ref:` émission des avertissements d’obsolescence <issuing-deprecation-warnings>`. Ajoutez une note d’édition avec une section ``dépréciations``qui répertorie tous les chemins obsolètes, leurs alternatives et la raison de l’obsolescence. Mise à jour des tests pour tester les avertissements.
Raison: les suppressions doivent être très visibles pour au moins une version, afin de minimiser la surprise pour les utilisateurs lorsqu’elles seront effectivement supprimées.
Définissez une date de suppression pour l’ancienne fonction et supprimez-la (ainsi que les avertissements) lorsque cette date est atteinte. Cela doit être au moins trois mois après que la version avec les avertissements a été publiée pour la première fois, et ne peut pas être la version mineure immédiatement après les avertissements. Ajoutez une note de mise à niveau
upgrade
qui répertorie toutes les suppressions. Par exemple, si le chemin alternatif a été fourni dans0.19.0
et que les avertissements ont été ajoutés dans0.20.0
, la version la plus ancienne pour le retrait est0.22.0
, même si0.21.0
a été publié plus de trois mois après0.20.0
.Note
Ces exigences sont le minimum. Pour retirer des fonctions importantes ou de base, accordez aux utilisateurs au moins une version secondaire supplémentaire si ce n’est plus.
Raison : il faut du temps pour que les utilisateurs puissent voir ces messages et leur donner le temps de s’ajuster. Tous les utilisateurs ne mettent pas à jour leur version de Qiskit immédiatement, et certains peuvent laisser passer des versions mineures.
Lorsqu’une fonctionnalité est marquée comme obsolète, elle est destinée à être supprimée, mais les utilisateurs devraient pouvoir compter sur elle pour fonctionner correctement. Nous considérons une fonctionnalité marquée « dépréciée » comme gelée ; nous nous engageons à le maintenir avec des corrections de bogues critiques jusqu’à ce qu’il soit supprimé, mais nous ne fusionnerons pas de nouvelles fonctionnalités.
Changement de comportement#
Changer le comportement sans retrait est particulièrement difficile à gérer, car nous avons besoin des deux options disponibles pour deux versions, et être en mesure d’émettre des avertissements. Par exemple, changer le type de la valeur de retour d’une fonction implique presque invariablement de faire une pause d’API, ce qui est frustrant pour les utilisateurs et rend difficile l’utilisation de Qiskit.
La meilleure solution ici est souvent de faire une nouvelle fonction, puis d’utiliser :ref:` les procédures de retrait <removing-features>` ci-dessus.
Si vous devez absolument changer le comportement du code existant (autre que la correction des bogues), vous devrez utiliser votre meilleur jugement pour appliquer les principes directeurs en haut de ce document. L’avertissement le plus approprié pour les changements de comportement est généralement FutureWarning
. Quelques possibilités pour effectuer un changement:
Si vous modifiez le comportement par défaut d’une fonction, pensez à ajouter un argument de mot clé pour sélectionner entre les anciens et les nouveaux comportements. Quand vient le temps, vous pouvez émettre un
FutureWarning
si l’argument du mot clé n’est pas donné (c’est à dire s’il est àNone
), en disant que la nouvelle valeur deviendra bientôt la valeur par défaut. Vous devrez passer par la période d’obsolescence normale pour supprimer cet argument de mot clé une fois que vous avez effectué le changement de comportement. Cela prendra au moins six mois pour traverser les deux cycles.Si vous devez modifier le type de retour d’une fonction, envisagez d’ajouter une nouvelle fonction qui renvoie le nouveau type, puis suivez les procédures d’obsolescence de l’ancienne fonction.
Si vous devez accepter une nouvelle entrée que vous ne pouvez pas distinguer d’une possibilité existante en raison de son type, pensez à le laisser passer par un autre argument de mot clé ou à ajouter une seconde fonction qui n’accepte que le nouveau formulaire.
Emission d’avertissements d’obsolescence#
The proper way to raise a deprecation warning is to use the decorators @deprecate_arg
and
@deprecate_func
from qiskit.utils.deprecation
. These will generate a standardized message and
and add the deprecation to that function’s docstring so that it shows up in the docs.
from qiskit.utils.deprecation import deprecate_arg, deprecate_func
@deprecate_func(since="0.24.0", additional_msg="No replacement is provided.")
def deprecated_func():
pass
@deprecate_arg("bad_arg", new_alias="new_name", since="0.24.0")
def another_func(bad_arg: str, new_name: str):
pass
Usually, you should set additional_msg: str `` with the format ``"Instead, use ..."
so that
people know how to migrate. Read those functions” docstrings for additional arguments like
pending: bool
and predicate
.
If you are deprecating outside the main Qiskit repo, set package_name
to match your package.
Alternatively, if you prefer to use your own decorator helpers, then have them call
add_deprecation_to_docstring
from qiskit.utils.deprecation
.
If @deprecate_func
and @deprecate_arg
cannot handle your use case, consider improving
them. Otherwise, you can directly call the warn
function
from the warnings module in the Python standard library, using the category
DeprecationWarning
. For example:
import warnings
def deprecated_function():
warnings.warn(
"The function qiskit.deprecated_function() is deprecated since "
"Qiskit Terra 0.20.0, and will be removed 3 months or more later. "
"Instead, you should use qiskit.other_function().",
category=DeprecationWarning,
stacklevel=2,
)
# ... the rest of the function ...
Assurez-vous d’inclure la version du paquet qui a introduit l’avertissement de dépréciation (pour que les responsables puissent facilement voir quand le moment est venu pour le supprimer), et quel est le chemin alternatif.
Prenez note de l’argument stacklevel
. Il permet de gérer les fonctions pointées comme obsolète. En définissant stacklevel=1
(la valeur par défaut), l’avertissement est responsable de la fonction warn
elle-même, tandis que stacklevel=2
va à juste titre désigner la fonction contenant. Il est inhabituel de la définir à autre chose que `` 2``, mais peut être utile si vous utilisez une fonction d’aide pour émettre le même avertissement dans plusieurs endroits.
Test des fonctionnalités obsolètes#
Chaque fois que vous ajoutez des avertissements de dépréciation, vous devrez mettre à jour les tests impliquant la fonctionnalité. La suite de tests devrait échouer autrement, en raison des nouveaux avertissements. Nous devons continuer à tester les fonctionnalités obsolètes tout au long de la période de dépréciation pour nous assurer que cela fonctionne toujours.
Pour mettre à jour les tests, vous devez encapsuler chaque appel de comportement obsolète dans son propre bloc d’assertion. Pour les sous-classes de unittest.TestCase
(que sont tous les scénarios de test Qiskit), ceci est effectué par:
class MyTestSuite(QiskitTestCase):
def test_deprecated_function(self):
with self.assertWarns(DeprecationWarning):
output = deprecated_function()
# ... do some things with output ...
self.assertEqual(output, expected)
Documenter les dépréciations et les modifications#
It is important to warn the user when your breaking changes are coming.
@deprecate_arg
and @deprecate_func
will automatically add the deprecation to the docstring
for the function so that it shows up in docs.
If you are not using those decorators, you should directly add a Sphinx deprecated directive
.. code-block:: python
- def deprecated_function():
« « » Short description of the deprecated function.
Obsolète depuis la version 0.20.0: The function qiskit.deprecated_function() is deprecated since Qiskit Terra 0.20.0, and will be removed 3 months or more later. Instead, you should use qiskit.other_function().
<rest of the docstring> « « » # … the rest of the function …
You should also document the deprecation in the changelog by using Reno. Explain the deprecation and how to migrate.
In particular situations where a deprecation or change might be a major disruptor for users, a
migration guide might be needed. Once the migration guide is written and published, deprecation
messages and documentation should link to it (use the additional_msg: str
argument for
@deprecate_arg
and @deprecate_func
).