Política de Descontinuação#
Muitos usuários e outros pacotes dependem de diferentes partes do Qiskit. Devemos garantir que, sempre que fizermos alterações no código, daremos aos usuários tempo suficiente para ajustar sem quebrar o código que já escreveram.
Mais importante: não altere nenhuma interface voltada para o público, a menos que seja absolutamente necessário. Adicionar coisas é bom, tirar coisas é irritante para os usuários, mas pode ser tratado razoavelmente com bastante antecedência, mas mudar o comportamento geralmente significa que os usuários não podem escrever código que funcionará com duas versões subsequentes do Qiskit, o que não é aceitável.
Esteja ciente de que os usuários frequentemente usarão funções, classes e métodos que nós, os desenvolvedores do Qiskit, podemos considerar internos ou não amplamente utilizados. Não faça suposições de que «isso está enterrado, então ninguém o usará»; se for público, está sujeito à política. As únicas exceções aqui são funções e módulos que são explicitamente internos, ou seja, aqueles cujos nomes começam com um sublinhado à esquerda (_
).
Os princípios orientadores são:
não devemos remover ou alterar o código sem avisos ativos por pelo menos três meses ou dois ciclos completos de versão;
deve haver sempre uma maneira de atingir metas válidas que não emita nenhum aviso;
nunca assuma que uma função que não é explicitamente interna não está em uso;
todas as reprovações, alterações e remoções são consideradas alterações de API e só podem ocorrer em versões secundárias, não em versões de patch, de acordo com a política de ramificação estável.
Removendo um recurso#
Ao remover um recurso (por exemplo, uma classe, função ou parâmetro de função), seguiremos este procedimento:
O caminho alternativo deve estar em vigor para uma versão secundária antes que qualquer aviso seja emitido. Por exemplo, se quisermos substituir a função
foo()
porbar()
, devemos fazer pelo menos um lançamento com ambas as funções antes de emitir qualquer aviso dentro defoo()
. Você pode emitirPendingDeprecationWarning
s dos caminhos antigos imediatamente.Razão: precisamos dar às pessoas tempo para trocar sem quebrar o código assim que atualizarem.
Depois que o caminho alternativo estiver em vigor para pelo menos uma versão secundária, emita os avisos de descontinuação. Adicione uma nota de lançamento com uma seção
deprecations
listando todos os caminhos obsoletos, suas alternativas e o motivo da descontinuação. Atualize os testes para testar os avisos.Razão: as remoções devem ser altamente visíveis para pelo menos uma versão, para minimizar a surpresa dos usuários quando eles realmente forem.
Defina uma data de remoção para o recurso antigo e remova-o (e os avisos) quando atingido. Isso deve ocorrer pelo menos três meses após o primeiro lançamento da versão com os avisos e não pode ser a versão secundária imediatamente após os avisos. Adicione uma nota de versão
upgrade
que lista todas as remoções. Por exemplo, se o caminho alternativo foi fornecido em0.19.0
e os avisos foram adicionados em0.20.0
, a versão mais antiga para remoção é0.22.0
, mesmo se0.21.0
foi lançado mais de três meses após0.20.0
.Nota
Estes são requisitos mínimos. Para a remoção de recursos significativos ou principais, forneça aos usuários pelo menos uma versão secundária extra, se esta não estiver disponivel.
Motivo: é preciso haver tempo para os usuários verem essas mensagens e dar-lhes tempo para se ajustarem. Nem todos os usuários atualizarão sua versão do Qiskit imediatamente e alguns podem pular versões secundárias.
Quando um recurso é marcado como obsoleto, ele está programado para remoção, mas os usuários ainda devem poder confiar que ele funcionará corretamente. Consideramos um recurso marcado como «obsoleto» como congelado; comprometemo-nos a mantê-lo com correções de bugs críticos até que seja removido, mas não vamos mesclar novas funcionalidades a ele.
Mudança de comportamento#
Alterar o comportamento sem uma remoção é particularmente difícil de gerenciar, porque precisamos ter as duas opções disponíveis por duas versões e poder emitir avisos. Por exemplo, alterar o tipo do valor de retorno de uma função quase invariavelmente envolve fazer uma quebra de API, o que é frustrante para os usuários e dificulta o uso do Qiskit.
A melhor solução aqui é criar uma nova função e então usar os procedimentos para remoção acima.
Se for absolutamente necessário alterar o comportamento do código existente (além de corrigir bugs), você precisará usar seu bom senso para aplicar os princípios orientadores no início deste documento. O aviso mais apropriado para mudanças de comportamento geralmente é FutureWarning
. Algumas possibilidades de como efetuar uma mudança:
Se você estiver alterando o comportamento padrão de uma função, considere adicionar um argumento de palavra-chave para selecionar entre comportamentos novos e antigos. Quando chegar a hora, você pode emitir um
FutureWarning
se o argumento da palavra-chave não for fornecido (por exemplo se forNone
), dizendo que o novo valor logo se tornará o padrão. Você precisará passar pelo período de descontinuação normal para remover esse argumento de palavra-chave depois de fazer a alteração de comportamento. Isso levará pelo menos seis meses para passar por ambos os ciclos.Se você precisar alterar o tipo de retorno de uma função, considere adicionar uma nova função que retorne o novo tipo e siga os procedimentos para substituir a função antiga.
Se você precisar aceitar uma nova entrada que não pode distinguir de uma possibilidade existente por causa de seu tipo, considere deixá-la ser passada por um argumento de palavra-chave diferente ou adicione uma segunda função que aceite apenas a nova forma.
Emitir avisos de descontinuação#
A maneira correta de emitir um aviso de descontinuação é usar os decoradores @deprecate_arg
e @deprecate_func
de qiskit.utils.deprecation
. Isso gerará uma mensagem padronizada e adicionará a descontinuação à docstring dessa função para que ela apareça na documentção.
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
Normalmente, você deve definir additional_msg: str `` com o formato ``"Em vez disso, use ..."
para que as pessoas saibam como migrar. Leia as docstrings dessas funções para obter argumentos adicionais como pending: bool
e 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
.
Se @deprecate_func
e @deprecate_arg
não puderem lidar com seu caso de uso, considere melhorá-los. Caso contrário, você pode chamar diretamente a função warn
do módulo warnings na biblioteca padrão do Python, usando a categoria `` DeprecationWarning``. Por exemplo:
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 ...
Certifique-se de incluir a versão do pacote que introduziu o aviso de descontinuação (para que os mantenedores possam ver facilmente quando é válido removê-lo) e qual é o caminho alternativo.
Tome nota do argumento stacklevel
. Isso controla qual função é acusada de ser obsoleta. Definir stacklevel=1
(o padrão) significa que o aviso culpará a própria função warn
, enquanto stacklevel=2
culpará corretamente a função que o contém. É incomum definir isso como algo diferente de 2
, mas pode ser útil se você usar uma função auxiliar para emitir o mesmo aviso em vários lugares.
Testando funcionalidade obsoleta#
Sempre que adicionar avisos de descontinuação, você precisará atualizar os testes envolvendo a funcionalidade. Caso contrário, o conjunto de testes deve falhar devido aos novos avisos. Devemos continuar a testar a funcionalidade obsoleta durante o período de descontinuação, para garantir que ela ainda funcione.
Para atualizar os testes, você precisa agrupar cada chamada de comportamento obsoleto em seu próprio bloco de asserção. Para subclasses de unittest.TestCase
(que são todos os casos de teste do Qiskit), isso é feito por:
class MyTestSuite(QiskitTestCase):
def test_deprecated_function(self):
with self.assertWarns(DeprecationWarning):
output = deprecated_function()
# ... do some things with output ...
self.assertEqual(output, expected)
Documentando depreciações e alterações importantes#
É importante avisar o usuário quando suas alterações importantes estiverem chegando.
@deprecate_arg
e @deprecate_func
irão adicionar automaticamente a depreciação à docstring para a função para que ela apareça nos documentos.
Se você não estiver usando esses decoradores, você deve adicionar diretamente uma diretiva obsoleta do Sphinx
.. code-block:: python
- def deprecated_function():
«»» Curta descrição da função descontinuada.
Obsoleto desde a versão 0.20.0: A função qiskit.deprecated_function() está descontinuada desde o Qiskit Terra 0.20.0 e será removida 3 meses ou mais depois. Em vez disso, você deve usar qiskit.other_function().
<rest of the docstring> «»» # … o resto da função …
Você também deve documentar a descontinuação no changelog usando Reno. Explique a descontinuação e como migrar.
Em situações específicas em que uma substituição ou alteração pode ser um grande obstáculo para os usuários, um guia de migração pode ser necessário. Depois que o guia de migração for escrito e publicado, as mensagens de descontinuação e a documentação devem ser vinculadas a ele (use o argumento additional_msg: str
para @deprecate_arg
e @deprecate_func
).