Skip to main content

pypncp — Cliente Python assíncrono para a API de Consulta do PNCP

Project description

pypncp

PyPI Python Version License

Cliente Python assíncrono para a API de Consulta do PNCP — Portal Nacional de Contratações Públicas.


Como usar

Adicionar ao projeto

Com uv (recomendado):

uv add pypncp

Com pip:

pip install pypncp

Ou direto no pyproject.toml:

[project]
dependencies = [
    "pypncp>=0.1",
]

Criar o cliente

O cliente é a entrada única para a API. Use async with pra gerenciar o ciclo de vida:

from pypncp import PNCPClient


async def buscar_dados():
    async with PNCPClient() as client:
        # client está pronto — usa os resources abaixo
        ...

# Fora de async def, use asyncio.run():
# asyncio.run(buscar_dados())

Exemplos por recurso

Contratos — busque contratos por período de publicação:

async with PNCPClient() as client:
    # Uma página
    page = await client.contratos.list(
        data_inicial="2025-01-01",
        data_final="2025-03-31",
    )
    for contrato in page.data:
        print(contrato.numero_contrato_empenho, contrato.valor_global)

    # Todas as páginas (paginação automática)
    async for contrato in client.contratos.list_all(
        data_inicial="2025-01-01",
        data_final="2025-03-31",
    ):
        print(contrato.objeto_contrato)

Contratações (licitações) — filtre por modalidade (código 1 = pregão):

async with PNCPClient() as client:
    async for compra in client.contratacoes.list_all_publicacao(
        data_inicial="2025-01-01",
        data_final="2025-03-31",
        codigo_modalidade=1,  # 1 = Pregão
    ):
        print(compra.objeto_compra, compra.orgao_nome)

    # Com propostas abertas (apenas data_final)
    async for compra in client.contratacoes.list_all_com_proposta(
        data_final="2025-12-31",
    ):
        print(compra.objeto_compra, compra.data_abertura_proposta)

Atas de registro de preço:

async with PNCPClient() as client:
    async for ata in client.atas.list_all(
        data_inicial="2025-01-01",
        data_final="2025-12-31",
    ):
        print(ata.objeto_contratacao, ata.orgao_nome)

Paginação

# Automática — use list_all*() (async generator)
async for contrato in client.contratos.list_all(
    data_inicial="2025-01-01",
    data_final="2025-12-31",
):
    ...


# Manual — use list() e controle a página
page = await client.contratos.list(
    data_inicial="2025-01-01",
    data_final="2025-12-31",
    pagina=1,
)
print(f"Página {page.numero_pagina} de {page.total_paginas}")
print(f"Itens nesta página: {len(page.data)}")

# Propriedades úteis de Page[T]:
#   page.data        → list[T]
#   page.numero_pagina
#   page.total_paginas
#   page.has_more    → True se há mais páginas

Tratamento de erros

Todas as exceções herdam de PNCPError — nunca vazam exceções de transporte:

from pypncp import PNCPError, NotFoundError, RateLimitError

try:
    page = await client.contratos.list(
        data_inicial="2025-01-01",
        data_final="2025-12-31",
    )
except NotFoundError:
    print("Recurso não encontrado (HTTP 404)")
except RateLimitError:
    print("Muitas requisições (HTTP 429)")
except PNCPError as e:
    print(f"Erro na API: {e}")

Exemplo completo com FastAPI

from fastapi import FastAPI, HTTPException
from pypncp import PNCPClient, NotFoundError

app = FastAPI()


@app.get("/contratos")
async def listar_contratos(
    data_inicial: str,
    data_final: str,
    pagina: int = 1,
):
    async with PNCPClient() as client:
        page = await client.contratos.list(
            data_inicial=data_inicial,
            data_final=data_final,
            pagina=pagina,
        )
        return {
            "contratos": [c.model_dump() for c in page.data],
            "pagina": page.numero_pagina,
            "total_paginas": page.total_paginas,
            "total_registros": page.total_registros,
        }


@app.get("/contratos/{orgao_cnpj}/{ano}/{sequencial}")
async def get_contrato(orgao_cnpj: str, ano: int, sequencial: int):
    async with PNCPClient() as client:
        try:
            contrato = await client.contratos.get(
                orgao_cnpj=orgao_cnpj,
                ano=ano,
                sequencial=sequencial,
            )
            return contrato.model_dump()
        except NotFoundError:
            raise HTTPException(status_code=404, detail="Contrato não encontrado")

Para contribuir

Requisitos

  • Python 3.12+
  • uv — gerenciador de projetos e pacotes
uv sync

Rodar verificações

git clone https://github.com/gabrielgz0/pypncp
cd pypncp
uv sync           # instala tudo — dev deps inclusas
uv run pytest -v  # tests
uv run ruff check src/ tests/
uv run mypy src/

Licença

MIT

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

pypncp-0.1.0.tar.gz (15.4 kB view details)

Uploaded Source

Built Distribution

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

pypncp-0.1.0-py3-none-any.whl (13.6 kB view details)

Uploaded Python 3

File details

Details for the file pypncp-0.1.0.tar.gz.

File metadata

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

File hashes

Hashes for pypncp-0.1.0.tar.gz
Algorithm Hash digest
SHA256 483b8e8da5c229db26b58c0348d4be175613bb2740c774c9727a508c4136984c
MD5 642390b3665414d45a8c1d688883eb13
BLAKE2b-256 7d3e16c019cbe2c823de57bfc2fe37ac3ebb381ea73d01b460a34e881f41d7cb

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypncp-0.1.0.tar.gz:

Publisher: ci.yml on gabrielgz0/pypncp

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

File details

Details for the file pypncp-0.1.0-py3-none-any.whl.

File metadata

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

File hashes

Hashes for pypncp-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 39614eef98b11d7c6faa577c30ed48f876ae452664e25a2b41f8b9b117a7ca33
MD5 27c2952dfe2c1ce191a22bb4827100d4
BLAKE2b-256 e367b4643b41d1de0b08d0cccb2ea5959c117ce535b1f989a0a145d865e3b723

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypncp-0.1.0-py3-none-any.whl:

Publisher: ci.yml on gabrielgz0/pypncp

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