datamais-api-python
Cliente Python da API DataMais da SECONV-RR (Governo do Estado de Roraima), feito para tornar triviais os bots de carga de dados ("cargas"): autentique com uma chave de API, leia as linhas atuais de uma fonte, envie um snapshot de substituição completo.
O código é escrito em português sem acentos, acompanhando a API e o seu wire;
apenas o nome de distribuição e de import continua datamais_api.
Instalação
uv add datamais-api
Ou direto do repositório:
uv add git+ssh://git@github.com/seconv-rr/datamais-api-python.git
Configuração
O cliente lê duas variáveis de ambiente; argumentos do construtor têm precedência sobre elas:
| Variável | Propósito |
|---|---|
DATAMAIS_BASE_URL |
URL base da API (ex.: https://api.datamais.example) |
DATAMAIS_API_KEY |
Segredo da chave de API (dmk_...) com concessões view/manage nas fontes alvo |
Sem DATAMAIS_BASE_URL, a construção do cliente levanta ErroConfigAusente.
DATAMAIS_API_KEY é opcional: omita-a para clientes somente-sessão, que
autenticam com entrar e um token Bearer em vez de uma chave de máquina.
Início rápido: um bot de carga
from datamais_api import ClienteDatamais, Coluna, TipoColuna
colunas = [
Coluna("convenio", "Convênio", TipoColuna.TEXTO, filtravel=True),
Coluna("valor_global", "Valor Global", TipoColuna.DINHEIRO),
Coluna("assinatura", "Assinatura", TipoColuna.DATA),
]
linhas = [
{"convenio": "923456/2026", "valor_global": 150000.0, "assinatura": "2026-07-01"},
]
with ClienteDatamais() as cliente:
cliente.substituir_dados_fonte("geral", "programas", colunas, linhas)
dados = cliente.obter_dados_fonte("geral", "programas")
print(dados.atualizado_em, len(dados.linhas))
substituir_dados_fonte substitui atomicamente o catálogo de colunas e as
linhas da fonte (PUT /v1/grupos/{grupo}/fontes/{slug}/dados); a chave de API
precisa possuir dataset:<grupo>:<slug>:manage (ou a equivalente em nível de
grupo, group:<grupo>:manage). obter_dados_fonte exige
dataset:<grupo>:<slug>:view, a menos que a fonte seja pública.
criar_fonte cadastra uma fonte em um grupo (POST /v1/grupos/{grupo}/fontes),
para que um bot de carga possa criar a fonte que está prestes a preencher:
from datamais_api import ClienteDatamais, ErroConflito
with ClienteDatamais() as cliente:
try:
cliente.criar_fonte("geral", "programas", "Programas", descricao="SICONV")
except ErroConflito:
pass
cliente.substituir_dados_fonte("geral", "programas", colunas, linhas)
acoes tem como padrão ACOES_FONTE_PADRAO (view, manage); a API sempre
acrescenta admin. A chave de API precisa de group:<grupo>:manage ou do
próprio dataset:<grupo>:<slug>:manage da fonte, e o grupo ainda precisa
existir e ter dono — uma chave não é um usuário, então ela nunca pode criar o
grupo. Uma fonte que já existe volta como ErroConflito; um grupo inexistente
ou sem dono, como ErroValidacao (422).
Layout de painel (autoria)
Além das cargas de fonte, o cliente lê e escreve o layout de um painel — a
DefinicaoPainel (abas, grade, widgets, fontes) guardada como JSONB:
from datamais_api import ClienteDatamais
with ClienteDatamais() as cliente:
cliente.entrar("autora@example.com", "segredo") # escrever layout exige sessão
definicao = cliente.obter_layout("geral", "convenios")
if definicao is not None:
cliente.substituir_layout("geral", "convenios", definicao)
A autenticação é resolvida a cada requisição: um token de sessão explícito
(ou um obtido com entrar) é enviado como Authorization: Bearer; caso
contrário vai o X-API-Chave. obter_layout aceita qualquer um dos dois (ou
nenhum, para painéis públicos) e retorna None quando o painel não tem
layout. substituir_layout é um endpoint de autoria — somente sessão,
então levanta ErroSessaoObrigatoria sem um entrar/token, e a API nunca
aceita uma chave de API para ele.
entrar retorna um ResultadoLogin (token mais Usuario) e None quando as
credenciais são recusadas — uma senha errada é um resultado esperado, não uma
exceção. eu lê a sessão de volta da mesma forma, e sair descarta o token.
Compor uma DefinicaoPainel em Python é trabalho do SDK de autoria irmão, o
datamais-sdk, que constrói e valida a definição e
a publica através deste cliente.
pandas
DadosPainel.para_dataframe() retorna as linhas como um DataFrame ordenado
pelo catálogo de colunas. Para cargas, substituir_dados_fonte_de_dataframe
envia um DataFrame inteiro em uma única chamada, inferindo o catálogo de
colunas a partir dos dtypes (bool → bool, inteiro → int, float →
number, datetime → datetime, o resto → text), a menos que uma lista
explícita de colunas seja passada. NaN e NaT viram null, e timestamps são
serializados como ISO-8601.
import pandas as pd
from datamais_api import ClienteDatamais
quadro = pd.read_csv("convenios.csv")
with ClienteDatamais() as cliente:
cliente.substituir_dados_fonte_de_dataframe("geral", "programas", quadro)
Vale a pena passar o catálogo explicitamente sempre que o painel se importa
com a renderização: a inferência não tem como adivinhar money, date,
link, percent nem quais colunas são filtravel.
Erros
Toda resposta não-2xx levanta uma exceção tipada carregando status,
detalhe e a lista estruturada erros da API:
ErroAutenticacao(401) — chave ausente, inválida, expirada ou revogadaErroProibido(403) — a chave não possui a permissão exigidaErroNaoEncontrado(404) — fonte desconhecida (grupo, slug)ErroConflito(409)ErroValidacao(422) — colunas/linhas malformadasErroAPI— qualquer outro status não-2xx
Todas são subclasses de ErroAPI, que por sua vez é subclasse de
ErroDatamais, ao lado de ErroConfigAusente e ErroSessaoObrigatoria.
Consumidores
datamais-cargas— os jobs de carga que alimentam as fontes.datamais-sdk— o SDK de autoria de painéis.
Publicação
Todo push na main roda o workflow de release: o python-semantic-release
calcula a próxima versão a partir dos Conventional Commits, escreve-a em
pyproject.toml e em src/datamais_api/__init__.py, cria a tag, atualiza o
changelog, compila com uv e — somente quando uma nova versão foi cortada —
publica no PyPI via uv publish, usando PyPI Trusted Publishing (sem
segredos de token).
Configuração única no PyPI: adicionar um trusted publisher para o projeto
datamais-api apontando para o repositório seconv-rr/datamais-api-python e
o workflow release.yml.
Desenvolvimento
uv sync # instala as dependências
uv run pytest # testes (offline, transporte mockado)
uv run ruff check src tests # lint
uv run ruff format src tests # formatação
uv run basedpyright src # checagem de tipos
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file datamais_api-0.3.0.tar.gz.
File metadata
- Download URL: datamais_api-0.3.0.tar.gz
- Upload date:
- Size: 19.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1bc701a18af2835b6bf446be8cfc7269c775715b788b0187cfb0c13a84c94eed
|
|
| MD5 |
825c9627a79003952527b7af76b47241
|
|
| BLAKE2b-256 |
f98fa9a7a19faada25110c31c6f4ece0185b17444df1022d2883a35ea2aab940
|
File details
Details for the file datamais_api-0.3.0-py3-none-any.whl.
File metadata
- Download URL: datamais_api-0.3.0-py3-none-any.whl
- Upload date:
- Size: 12.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
078352488f6d865e5b0dd8c6fb90937de756f9ed9fcf264454978b4cc54177d3
|
|
| MD5 |
fecf6a872fc01cd7fa923c40dec8a171
|
|
| BLAKE2b-256 |
dd778e3700d56d24603ec5fdc6f0d022ca1657b319a620dbaa387e902bac1795
|