Skip to main content

Normalização de processos judiciais brasileiros — multi-fonte, multi-output

Project description

pyjuris

Pacote Python para normalização de processos judiciais brasileiros.

Recebe payloads brutos de fontes externas (Escavador, futuramente Solucionare) e entrega JSON padronizado para consumidores internos do ecossistema LOPS (lops_api, lops_agents).

  • Stateless — funções puras, sem estado interno
  • Idempotente — mesma entrada, mesma saída
  • Sem descartes — dados incompletos entram com flags, nunca são perdidos
  • Sem IA — transformações explícitas e auditáveis por regras

Instalação

# Core (sem dependências externas)
pip install -e .

# Com CLI (flask, pymongo, rich)
pip install -e ".[cli]"

# Com testes
pip install -e ".[dev]"

Requisito: Python 3.11+


Início rápido

from pyjuris import normalizar_processo

with open("processo.json") as f:
    payload = json.load(f)

result = normalizar_processo(payload)
# → dict padronizado pronto para persistir no lops_api

API

normalizar_processo

Ponto de entrada principal. Transforma payload bruto em JSON normalizado.

from pyjuris import normalizar_processo

result = normalizar_processo(payload)

# Explícito (equivalente ao padrão)
result = normalizar_processo(
    payload,
    input_template="escavador",   # fonte dos dados
    output_template="lops_api",   # formato de saída
    enrich_orgaos=True,           # estrutura orgao_julgador automaticamente
)

# Sem enriquecimento de órgão (bulk processing sem necessidade do campo)
result = normalizar_processo(payload, enrich_orgaos=False)

Saída:

{
  "numero_cnj": "1004370-10.2025.8.26.0590",
  "tipo_principal": "RECURSO",
  "fase_atual": "SEGUNDO_GRAU",
  "status_geral": "ATIVO",
  "total_instancias": 2,
  "segredo_justica": false,
  "capa_disponivel": true,
  "tem_audiencia": false,
  "tem_multiplas_instancias_ativas": true,
  "fenomenos_detectados": [
    "inversao_polo:08057867833",
    "multiplas_instancias_ativas"
  ],
  "ano_inicio": 2025,
  "data_inicio": "2025-04-11",
  "data_ultima_movimentacao": "2025-10-02",
  "data_ultima_verificacao": "2025-10-08T12:30:39Z",
  "polo_ativo": "Thial Felix da Silva",
  "polo_passivo": "Banco Agibank S.A",
  "instancias": [ ... ],
  "schema_version": "1.0",
  "_etl": {
    "processado_em": "2026-03-12T21:00:00Z",
    "versao_etl": "1.0.0",
    "fonte_origem": "escavador"
  }
}

resumo

Texto legível para humanos — útil em logs e CLIs.

from pyjuris import resumo

print(resumo(result))
────────────────────────────────────────────────────────
  Processo   1004370-10.2025.8.26.0590
  Tipo       RECURSO
  Fase       SEGUNDO_GRAU
  Status     ATIVO
  Polo ativo   Thial Felix da Silva
  Polo passivo Banco Agibank S.A
  Instâncias 2 ⚠ múltiplas ativas
  Distribuição        2025-04-11
  Última movimentação 2025-10-02

  Alertas:
    ⚠  Polo ativo e passivo invertidos entre graus do processo
    ⚠  Processo ativo simultaneamente em mais de uma instância
────────────────────────────────────────────────────────

should_reprocess

Decide se um processo deve ser reprocessado comparando datas de movimentação.

from pyjuris import should_reprocess

should_reprocess("2025-09-01", "2025-10-02")  # → True  (incoming mais recente)
should_reprocess("2025-10-02", "2025-10-02")  # → False (mesma data)
should_reprocess(None, "2025-10-02")          # → True  (sem dado armazenado)

descrever_fenomeno / descrever_fenomenos

Converte códigos de fenômenos em descrições legíveis em português.

from pyjuris import descrever_fenomeno, descrever_fenomenos

descrever_fenomeno("inversao_polo:12345678900")
# → "Polo ativo e passivo invertidos entre graus do processo"

descrever_fenomenos(result["fenomenos_detectados"])
# → [{"codigo": "inversao_polo:...", "descricao": "..."}, ...]

Fenômenos disponíveis:

Código Descrição
cnj_invalido Número CNJ fora do formato padrão
sem_fontes Nenhuma fonte judicial encontrada
multiplas_instancias_ativas Processo ativo em mais de uma instância
duplicata_ingestao Fonte duplicada detectada na mesma instância
redistribuicao Redistribuição identificada entre fontes do mesmo grau
crawl_duplicado Coleta duplicada da mesma fonte
recursos_distintos Recursos distintos no mesmo grau
inversao_polo:<doc> Polo ativo/passivo invertidos entre graus

CNJParser

Resolve tribunal_sigla, estado e comarca a partir do número CNJ — sem consultas externas.

from pyjuris import CNJParser

parser = CNJParser()

# Resolução básica (tabela estática + 6.797 pares OOOO→comarca)
r = parser.parse("0001234-56.2023.8.26.0536")
# {
#   'tribunal_sigla': 'TJSP',
#   'tribunal_nome':  'TJ de São Paulo',
#   'estado':         'SP',
#   'comarca':        'Santos',
#   'confianca':      'referencia',
#   'segmento':       'Justiça Estadual',
#   'oooo':           '0536',
# }

# Com dados do Escavador (confiança máxima)
r = parser.parse(
    "0001234-56.2023.8.26.0536",
    unidade_origem={"nome": "3ª Vara Cível de Santos", "tribunal_sigla": "TJSP"},
)
# confianca: 'escavador'

Níveis de confiança:

Valor Significado
escavador Dado direto de unidade_origem
referencia OOOO resolvido via tabela com 6.797 pares
tribunal Só tribunal resolvido — comarca desconhecida
none CNJ inválido

Cobertura (sobre 9,5M processos reais): ~68% referencia · ~17% precisa de unidade_origem · ~15% só tribunal.

Também disponível: normalizar_comarca(nome_unidade) — extrai cidade a partir do nome da vara/foro do Escavador.

from pyjuris import normalizar_comarca

normalizar_comarca("17ª Vara do Trabalho de Manaus")  # → "Manaus"
normalizar_comarca("FORO REGIONAL II - SANTO AMARO")  # → "Santo Amaro"
normalizar_comarca("COMARCA DE CAMPINAS")             # → "Campinas"

get_orgaos / parsear_orgao / get_tribunais

Referência de órgãos julgadores brasileiros — 32k+ órgãos de 64 tribunais, bundled com o pacote.

from pyjuris import get_tribunais, get_orgaos, parsear_orgao

# Lista todos os tribunais disponíveis
get_tribunais()
# → ["STJ", "TJSP", "TJRS", "TRF1", "TRT1", ...]  (64 tribunais)

# Órgãos estruturados de um tribunal
get_orgaos("TJRS")[9]
# → {
#     "nome_original": "10ª Vara Criminal do Foro Central - Porto Alegre",
#     "nome_normalizado": "10ª Vara Criminal do Foro Central - Porto Alegre",
#     "encoding_status": "ok",
#     "tipo": "VARA",
#     "numero": 10,
#     "especialidade": "CRIMINAL",
#     "localidade": "Porto Alegre",
#     "cargo": None,
#     "nome_pessoa": None
#   }

# Parsing avulso de qualquer string
parsear_orgao("3ª Vara da Fazenda Pública - Belo Horizonte")
# → {"tipo": "VARA", "numero": 3, "especialidade": "FAZENDA_PUBLICA",
#    "localidade": "Belo Horizonte", "cargo": None, "nome_pessoa": None}

parsear_orgao("GABINETE DA MINISTRA NANCY ANDRIGHI")
# → {"tipo": "GABINETE", "numero": None, "especialidade": None,
#    "localidade": None, "cargo": "Ministra", "nome_pessoa": "Nancy Andrighi"}

O campo orgao_julgador_info é adicionado automaticamente em cada instância pelo normalizar_processo (controlado por enrich_orgaos=True).

Tipos de órgão: VARA, CAMARA, TURMA, TURMA_RECURSAL, GABINETE, JUIZADO_ESPECIAL, JUIZADO_ESPECIAL_FEDERAL, JUIZADO, CEJUSC, UNIDADE_JURISDICIONAL, NUCLEO, GRUPO, SUBSECAO, SECAO, PRESIDENCIA, CORREGEDORIA, DIRETORIA, SECRETARIA, PLENARIO, OUTRO

Especialidades: CIVEL, CRIMINAL, FAZENDA_PUBLICA, EXECUCAO_FISCAL, PREVIDENCIARIO, FAMILIA, ORFAOS_SUCESSOES, INFANCIA_JUVENTUDE, CONSUMIDOR, TRABALHISTA, ACIDENTES_TRABALHO, ELEITORAL, MILITAR, PLANTAO, AMBIENTAL, EMPRESARIAL, PROPRIEDADE_INTELECTUAL, RECUPERACAO_JUDICIAL, AGRARIO, TRIBUTARIO


CLI

# Pipe: stdin → stdout
cat processo.json | pyjuris

# Resumo legível
cat processo.json | pyjuris --resumo

# Arquivo → arquivo
pyjuris -i processo.json -o resultado.json

# Batch: diretório inteiro
pyjuris -i ./jsons/ -o ./output/

# Templates explícitos
pyjuris --input-template escavador --output-template lops_api < processo.json

# Servidor HTTP local (porta 5045)
pyjuris --api

Servidor HTTP (--api):

Endpoint Método Descrição
POST /transform JSON body Normaliza um processo
POST /upload multipart Upload de arquivo JSON
GET / Health check

Schema de saída

Processo (topo)

Campo Tipo Valores
numero_cnj string | null Formato NNNNNNN-DD.AAAA.J.TT.OOOO
tipo_principal enum ACAO_ORIGINAL, RECURSO, CUMPRIMENTO_SENTENCA, RECURSO_INTERMEDIARIO, DESCONHECIDO
fase_atual enum PRIMEIRO_GRAU, SEGUNDO_GRAU, TERCEIRO_GRAU, ENCERRADO, DESCONHECIDO
status_geral enum ATIVO, INATIVO
total_instancias integer
segredo_justica boolean
capa_disponivel boolean
tem_audiencia boolean
tem_multiplas_instancias_ativas boolean
fenomenos_detectados string[] Ver tabela de fenômenos
ano_inicio integer | null
data_inicio date | null YYYY-MM-DD
data_ultima_movimentacao date | null YYYY-MM-DD
data_ultima_verificacao datetime | null ISO 8601
polo_ativo string | null Nome da parte ativa principal
polo_passivo string | null Nome da parte passiva principal
instancias Instancia[] Ver abaixo
schema_version string "1.0"
_etl object processado_em, versao_etl, fonte_origem

Instância

Campo Tipo Valores
fonte_id integer | null
grau enum 1, 2, 3
grau_formatado enum Primeiro Grau, Segundo Grau, Terceiro Grau
tipo enum Mesmo que tipo_principal
tribunal object sigla, nome, sistema
classe string | null Classe normalizada pelo ETL
classe_raw string | null Classe original da fonte
assunto_principal string | null
assunto_path string | null Ex: DIREITO DO CONSUMIDOR > Bancários
assuntos Assunto[] {id, nome, path}
orgao_julgador string | null String original
orgao_julgador_info OrgaoJulgador | null Parsing estruturado (ver acima)
valor_causa number | null Em BRL
moeda enum BRL, null
data_inicio date | null
data_ultima_movimentacao date | null
status enum ATIVO, INATIVO
arquivado boolean | null
capa_disponivel boolean
partes Parte[] Ver abaixo
audiencias array

Parte

Campo Tipo Valores
nome string | null
polo enum ATIVO, PASSIVO, ADVOGADO, DESCONHECIDO
tipo enum FISICA, JURIDICA, DESCONHECIDO, null
tipo_pessoa enum FISICA, JURIDICA, DESCONHECIDO, null
documento string | null CPF ou CNPJ sem formatação
advogados array

Arquitetura

payload bruto (Escavador | Solucionare)
    ↓ pyjuris/inputs/<template>.parse()
canonical dict          ← formato interno, nunca exposto diretamente
    ↓ pyjuris/outputs/<template>.serialize()
output final (lops_api | solucionare)
    ↓ pipeline.py (enrich_orgaos=True)
+ orgao_julgador_info em cada instância

O pipeline tem 6 camadas internas (aplicadas em inputs/escavador.py):

  1. Sanitização — normaliza strings e datas antes de qualquer lógica
  2. Classificação — mapeia classe processual para tipos canônicos
  3. Deduplicação — remove fontes duplicadas, detecta redistribuições
  4. Normalização — constrói objetos por instância judicial
  5. Detecção de fenômenos — inversão de polo, múltiplas instâncias ativas
  6. Transform — orquestra o pipeline e monta o canonical

Adicionar nova fonte de dados (input)

# 1. Criar pyjuris/inputs/nova_fonte.py
def parse(payload: dict) -> dict:
    """Converte payload bruto para canonical dict."""
    ...

# 2. Registrar em pyjuris/inputs/__init__.py
# 3. Usar: normalizar_processo(payload, input_template="nova_fonte")

Adicionar novo consumidor (output)

# 1. Criar pyjuris/outputs/novo_consumidor.py
def serialize(canonical: dict, etl_version: str) -> dict:
    """Converte canonical para formato do consumidor."""
    ...

# 2. Registrar em pyjuris/outputs/__init__.py
# 3. Usar: normalizar_processo(payload, output_template="novo_consumidor")

Testes

# Suite completa
pytest tests/ -v

# Smoke test com uso real
python scripts/testar_lib.py
python scripts/testar_lib.py --verboso

Scripts utilitários

Script Descrição
scripts/testar_lib.py Smoke test de uso real (não pytest)
scripts/sanear_orgaos.py Gera data/orgaos_julgadores_v2.json para inspeção
scripts/eda_escavador.py Análise exploratória de payloads no MongoDB
scripts/analyze_classe_score.py Análise de cobertura de mapeamento de classes

Migrações de banco

Scripts em migrations/ para evolução do schema MongoDB/PostgreSQL:

python migrations/migration_0001_enums_e_dominios.py
python migrations/migration_0002_rename_e_tipos.py
python migrations/migration_0003_indices.py

Schema SQL completo em docs/schema_banco.sql.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyjuris-2.0.0.tar.gz (340.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyjuris-2.0.0-py3-none-any.whl (331.3 kB view details)

Uploaded Python 3

File details

Details for the file pyjuris-2.0.0.tar.gz.

File metadata

  • Download URL: pyjuris-2.0.0.tar.gz
  • Upload date:
  • Size: 340.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pyjuris-2.0.0.tar.gz
Algorithm Hash digest
SHA256 09120ce1e45f8cf4bd957c35aafcd92c22cce00fb0c149056010cb9ce88139b1
MD5 c09a35d2e44ce1f58671c25211d00777
BLAKE2b-256 2322ad44da35c1f08b47cc9da0bd4486d165320f64db29ac492f899c1d21b6e7

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyjuris-2.0.0.tar.gz:

Publisher: publish.yml on autodevx/pyjuris

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyjuris-2.0.0-py3-none-any.whl.

File metadata

  • Download URL: pyjuris-2.0.0-py3-none-any.whl
  • Upload date:
  • Size: 331.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pyjuris-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4a2b4811ca7911bdb927a70566b1bcb3ffef1627508e95dae1ad30cf53d1fa0c
MD5 0f8a4f7ee8b103fd2f3d6c17885cf845
BLAKE2b-256 5e7e7c249a42fbea915c4ea29765fc60c19d8fd60da1436626eb6e380db53e7d

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyjuris-2.0.0-py3-none-any.whl:

Publisher: publish.yml on autodevx/pyjuris

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page