enum.verify: valide regras de Enum no Python

Publicado em: 06/09/2026
Tempo de leitura: 6 minutos
Código Python validado com enum.verify

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.

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.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Grafo de dependências e fluxo de tarefas com TopologicalSorter no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    TopologicalSorter: ordene dependências sem ciclos

    Aprenda TopologicalSorter no Python para ordenar dependências, detectar ciclos e executar pipelines sequenciais ou paralelos com segurança.

    Ler mais

    Tempo de leitura: 6 minutos
    06/09/2026
    Pastas e diretórios representando os.fwalk no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    os.fwalk no Python: percorra diretórios

    Aprenda os.fwalk no Python para percorrer diretórios com descritores, reduzir condições de corrida e manipular arquivos com mais segurança.

    Ler mais

    Tempo de leitura: 5 minutos
    05/09/2026
    Desenvolvedor revisando código Python e métodos sobrescritos
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    typing.override: valide sobrescritas de métodos

    Aprenda typing.override no Python para validar sobrescritas, assinaturas, refatorações e contratos de herança com análise estática.

    Ler mais

    Tempo de leitura: 5 minutos
    05/09/2026
    Desenvolvedor trabalhando com filas e threads em Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    queue.SimpleQueue: fila FIFO segura entre threads

    Aprenda queue.SimpleQueue no Python para criar filas FIFO seguras entre threads, organizar workers e evitar erros de concorrência.

    Ler mais

    Tempo de leitura: 5 minutos
    04/09/2026
    Desenvolvedor trabalhando com enums e código Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    StrEnum no Python: enums como strings

    Aprenda StrEnum no Python para criar enums como strings, validar entradas, serializar JSON e organizar APIs e configurações.

    Ler mais

    Tempo de leitura: 4 minutos
    04/09/2026
    Pastas e diretórios para contextlib.chdir no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    contextlib.chdir: restaure o diretório automaticamente

    Aprenda contextlib.chdir no Python para trocar diretórios temporariamente com segurança, testes confiáveis e restauração automática do caminho.

    Ler mais

    Tempo de leitura: 5 minutos
    03/09/2026