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.1.tar.gz (15.6 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.1-py3-none-any.whl (13.7 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: pypncp-0.1.1.tar.gz
  • Upload date:
  • Size: 15.6 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.1.tar.gz
Algorithm Hash digest
SHA256 62468d2f599c3d335c104b4df77c502d0ba5724fa21944b4ed09aeb173260fec
MD5 c95de9f922090c90858a4700052f0f7f
BLAKE2b-256 791cf8a36a53ac60f6080e0891596cf026968dc17cb05b86047741224e11c751

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypncp-0.1.1.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.1-py3-none-any.whl.

File metadata

  • Download URL: pypncp-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 13.7 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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 d08984481df7c9e004a7f718caa02fbf3cd776fd04d6fdad88da2a5f496a8a45
MD5 3a9c58587e72e1aa29883797ecb821ec
BLAKE2b-256 2a675669ed5d094e02373f01e7dabd10f8101578b24a4f9effaafe682e90957a

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypncp-0.1.1-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