enum.verify é um recurso da biblioteca padrão do Python usado para validar regras de uma enumeração no momento em que a classe é criada. Ele ajuda a detectar problemas antes que a enum seja usada em produção, como valores duplicados, lacunas inesperadas em sequências numéricas ou combinações inválidas em flags. Em sistemas que dependem de códigos estáveis, permissões, estados ou protocolos, essa validação reduz erros silenciosos e torna o contrato da enum mais explícito.
O recurso trabalha com o decorador verify() e com verificadores prontos como UNIQUE, CONTINUOUS e NAMED_FLAGS. Em vez de escrever testes manuais para cada classe, você declara a regra junto da própria enum. Se a regra for violada, o Python levanta um erro durante a definição da classe.
Por que validar enums
Enums são frequentemente usadas para representar estados, códigos de retorno, tipos de evento, níveis de acesso e categorias de domínio. O problema é que uma enum mal definida pode continuar funcionando por muito tempo. Dois nomes podem compartilhar o mesmo valor sem intenção, uma sequência pode pular números importantes ou uma flag composta pode usar bits sem nomes correspondentes.
Esses defeitos costumam aparecer apenas quando outro sistema consome os valores, quando um banco de dados espera uma faixa específica ou quando a serialização encontra aliases inesperados. enum.verify desloca essa falha para o início da aplicação, onde é mais simples diagnosticar.
Validando valores únicos com UNIQUE
from enum import Enum, verify, UNIQUE
@verify(UNIQUE)
class Status(Enum):
PENDENTE = 1
PROCESSANDO = 2
CONCLUIDO = 3
Nesse exemplo, todos os valores são distintos. Se dois membros usarem o mesmo número, a criação da classe falha:
@verify(UNIQUE)
class Status(Enum):
PENDENTE = 1
PROCESSANDO = 2
FINALIZADO = 2
Sem UNIQUE, FINALIZADO seria tratado como alias de PROCESSANDO. Aliases podem ser úteis para compatibilidade, mas devem ser deliberados. Em enums de protocolo, banco ou API, valores duplicados acidentais geram ambiguidade.
Quando aliases são aceitáveis
Nem todo alias é um erro. Durante uma migração, um nome antigo pode continuar existindo apontando para o novo valor. Nesse caso, não use UNIQUE ou mantenha a compatibilidade em uma camada externa. O ponto principal é tornar a decisão explícita.
Se aliases forem necessários temporariamente, documente o motivo, defina uma data de remoção e teste a serialização. Isso evita que clientes externos passem a depender do nome obsoleto.
Sequências contínuas com CONTINUOUS
from enum import IntEnum, verify, CONTINUOUS
@verify(CONTINUOUS)
class Prioridade(IntEnum):
BAIXA = 1
MEDIA = 2
ALTA = 3
CONTINUOUS verifica se todos os valores inteiros entre o menor e o maior foram usados. Se a sequência saltar de 1 para 3, a classe é rejeitada. Isso é útil quando cada número representa uma posição contínua, um índice ou uma etapa de processo.
Não use essa regra quando lacunas fizerem parte do contrato. Códigos HTTP, por exemplo, não são contínuos. Em protocolos legados, intervalos podem estar reservados. A verificação correta depende do significado do domínio, não apenas da estética dos números.
Exemplo de lacuna detectada
@verify(CONTINUOUS)
class Etapa(IntEnum):
INICIO = 1
VALIDACAO = 2
PUBLICACAO = 4
O valor 3 está ausente. Se isso for um erro, a validação impede a enum de existir. Se a lacuna for intencional, remova CONTINUOUS e documente o intervalo reservado.
Flags nomeadas com NAMED_FLAGS
from enum import Flag, verify, NAMED_FLAGS
@verify(NAMED_FLAGS)
class Permissao(Flag):
LER = 1
ESCREVER = 2
EXCLUIR = 4
ADMIN = LER | ESCREVER | EXCLUIR
NAMED_FLAGS verifica se aliases e combinações usam somente bits que também possuem nomes válidos. Isso é importante porque uma máscara composta pode incluir um bit desconhecido, criando permissões que não podem ser interpretadas corretamente.
Com flags, prefira potências de dois para os membros básicos. As combinações podem usar o operador |. Quando cada bit tem um nome claro, logs, depuração e auditoria ficam mais confiáveis.
Combinando verificações
from enum import IntEnum, verify, UNIQUE, CONTINUOUS
@verify(UNIQUE, CONTINUOUS)
class Nivel(IntEnum):
INICIANTE = 1
INTERMEDIARIO = 2
AVANCADO = 3
O decorador aceita mais de uma regra. Nesse caso, a enum precisa ter valores únicos e contínuos. Combine verificações apenas quando ambas representarem o contrato real.
Erros na inicialização da aplicação
A validação acontece durante a criação da classe. Em muitos projetos, isso ocorre na importação do módulo. Portanto, uma enum inválida pode impedir a aplicação de iniciar. Esse comportamento é desejável para erros de contrato, mas deve ser considerado em ferramentas de plugin ou ambientes que carregam módulos dinamicamente.
Em aplicações críticas, cubra as enums com testes de importação e execute esses testes no pipeline de integração contínua. Assim, a falha aparece antes do deploy.
Enum, IntEnum e Flag
Enum cria membros simbólicos sem comportamento numérico implícito. IntEnum permite interoperabilidade com inteiros, o que pode ser necessário em bancos, bibliotecas antigas e protocolos. Flag representa combinações de bits.
Escolha o tipo mais restrito possível. Se o valor não precisa agir como inteiro, prefira Enum. Se diferentes permissões precisam ser combinadas, use Flag ou IntFlag. A validação com verify complementa essa escolha.
Integração com APIs e bancos
Ao persistir enums, decida se o banco armazenará o nome ou o valor. Nomes são mais legíveis, mas mudanças de nomenclatura exigem migração. Valores são compactos, porém precisam permanecer estáveis. UNIQUE ajuda a evitar colisões quando valores são persistidos.
Em APIs, serialize de forma consistente. Não exponha ora o nome, ora o número. Crie uma camada de conversão e valide entradas desconhecidas. O fato de a enum estar correta não elimina a necessidade de tratar dados externos inválidos.
Testando enums verificadas
def test_status_values():
assert Status.PENDENTE.value == 1
assert Status.CONCLUIDO.name == "CONCLUIDO"
def test_prioridades_continuas():
valores = [item.value for item in Prioridade]
assert valores == [1, 2, 3]
O decorador protege a definição, mas testes ainda são úteis para garantir valores públicos, serialização e compatibilidade. Se os números fazem parte de um contrato externo, trate mudanças como alterações de API.
Boas práticas
Use nomes claros, evite mudar valores já publicados, documente aliases intencionais, escolha verificadores de acordo com o domínio e mantenha as enums próximas da lógica que representam. Não use CONTINUOUS apenas porque uma sequência parece mais organizada. Não use UNIQUE quando aliases fazem parte de uma estratégia de compatibilidade conscientemente planejada.
Prefira membros básicos simples e combinações explícitas em flags. Para grandes catálogos controlados por terceiros, considere gerar a enum a partir de uma fonte oficial e validar o resultado em testes.
Links relacionados
Na Academify, complemente o estudo com dicionários em Python, conjuntos em Python, classes em Python e dataclasses em Python. Consulte também a documentação oficial do módulo enum e a PEP 435, que descreve a inclusão de enums no Python.
Conclusão
enum.verify transforma regras implícitas em validações executáveis. Com UNIQUE, você evita aliases acidentais. Com CONTINUOUS, detecta lacunas indevidas. Com NAMED_FLAGS, protege máscaras de bits contra combinações sem nomes válidos. O resultado é uma enum mais previsível, fácil de auditar e segura para uso em APIs, bancos, permissões e fluxos de negócio.







