This project is an implementation of the Hipolita framework
Project description
HLib
Descrição
Implementação do framework Hipólita, proposto originalmente em Hippolyta: a framework to enhance open data interpretability and empower citizens.
Hlib facilita o acesso e a interpretação de dados governamentais abertos, fornecendo uma interface unificada para buscar, recuperar e consumir datasets de múltiplos portais nacionais — cada um com APIs, padrões de metadados e formatos de resposta diferentes.
Portais Suportados
| Portal | País | URL | Chave (PortalType) |
Plataforma / API | Autenticação |
|---|---|---|---|---|---|
| Portal de Dados Abertos | Brasil 🇧🇷 | dados.gov.br | DADOS_GOV_BR |
REST API própria | Requer api_key |
| Data.gov | EUA 🇺🇸 | data.gov | DATA_GOV_US |
Catalog API v4 (DCAT-US) | X-Api-Key (DEMO_KEY público funciona) |
| CKAN Publishing | Reino Unido 🇬🇧 | ckan.publishing.service.gov.uk | DATA_GOV_UK |
CKAN v3 | Acesso público |
| opendata.swiss | Suíça 🇨🇭 | opendata.swiss | OPENDATA_SWISS |
CKAN v3 (multilíngue) | Acesso público |
| Avoindata.fi | Finlândia 🇫🇮 | avoindata.fi | AVOINDATA_FI |
CKAN v3 | Acesso público |
| data.gov.au | Austrália 🇦🇺 | data.gov.au | DATA_GOV_AU |
CKAN v3 | Acesso público |
| data.gouv.fr | França 🇫🇷 | data.gouv.fr | DATA_GOUV_FR |
udata REST API | Acesso público |
| datos.gob.es | Espanha 🇪🇸 | datos.gob.es | DATOS_GOB_ES |
Linked Data API | Acesso público |
| data.gov.sg | Singapura 🇸🇬 | data.gov.sg | DATA_GOV_SG |
REST API v2 | Acesso público |
| data.gov.in | Índia 🇮🇳 | data.gov.in | DATA_GOV_IN |
OGDP REST API | Acesso público |
Autenticação: dois portais precisam de chave de API, cada um passada via
api_key=na instância/chamada daquele portal (não é compartilhada entre portais — ver exemplo de busca em lista acima):
- BR (
dados.gov.br) — obrigatória, sem elasearch()/get_dataset()levantamValueError. Solicite em dados.gov.br.- EUA (
data.gov) — opcional para uso leve: semapi_key, usa aDEMO_KEYpública (limite baixo de requisições/hora). Para uso mais intenso, registre uma chave própria em api.data.gov/signup.
Portais Investigados (Sem Integração Programática)
| Portal | País | Motivo |
|---|---|---|
| data.gov.cy | Chipre 🇨🇾 | Portal Drupal sem API REST pública |
| data.gov.ru | Rússia 🇷🇺 | SPA Vue.js sem endpoint de API acessível |
| data.gv.at | Áustria 🇦🇹 | Migrou para SPA; CKAN API desativada |
| data.gov.tw | Taiwan 🇹🇼 | API v1 desativada; v2 requer chave de autenticação |
Instalação
pip install hlib-hipolita
Requer Python 3.10+. Dependências: pandas, numpy, aiohttp.
Como Usar
Busca de Datasets (search_data)
Busca datasets por texto em um ou mais portais simultaneamente.
from hlib import search_data, PortalType
# Busca em um portal específico
datasets = search_data("climate", portal=PortalType.DATA_GOV_US)
# Também aceita string no lugar do enum
datasets = search_data("education", portal="data_gov_uk")
# Busca em vários portais em paralelo — cada item da lista pode ser um
# PortalType/string simples, ou um dict com a config específica daquele
# portal (ex: api_key). A config de um portal nunca vaza para os outros.
datasets = search_data("saúde", portal=[
{"portal": PortalType.DADOS_GOV_BR, "api_key": "SUA_CHAVE_BR"},
{"portal": "data_gov_us", "api_key": "SUA_CHAVE_US"}, # opcional, usa DEMO_KEY se omitido
"data_gov_uk",
])
Não existe mais um valor
PortalType.ALL— como cada portal pode precisar de uma config diferente (ver seção de autenticação abaixo), buscar em vários portais exige listá-los explicitamente, como no exemplo acima.
Controle de erros (fails_silently)
# Se o portal estiver offline ou a chave for inválida, retorna [] ao invés de lançar exceção
datasets = search_data("health", portal=PortalType.DADOS_GOV_BR, fails_silently=True)
Busca de Dataset Individual (get_dataset)
Recupera os metadados completos de um dataset específico pelo seu ID.
from hlib import get_dataset, PortalType
# Buscar um dataset por ID
dataset = get_dataset("dataset-id-123", portal=PortalType.DATA_GOV_US)
if dataset:
print(dataset.title)
print(dataset.description)
for resource in dataset.resources:
print(f" {resource.name} ({resource.format}): {resource.url}")
Download e Parse de Dados (fetch_dataset_data)
Busca um dataset e, se houver um recurso em formato parseável (CSV, TSV, XLS, XLSX, JSON), retorna os dados como pandas.DataFrame.
from hlib import fetch_dataset_data, PortalType
result = fetch_dataset_data("dataset-id-123", portal=PortalType.DATA_GOV_AU)
if not result.df.empty:
# Dados parseados com sucesso
print(result.df.head())
print(f"Formato: {result.meta['format']}")
print(f"URL: {result.meta['resource_url']}")
else:
# Sem recurso parseável — metadados disponíveis com links
print(f"Dataset: {result.meta.get('title')}")
for link in result.meta.get("resource_links", []):
print(f" {link['name']} ({link['format']}): {link['url']}")
Uso Assíncrono (asyncio)
Todas as funções possuem versão assíncrona com sufixo _async:
import asyncio
from hlib import search_data_async, get_dataset_async, fetch_dataset_data_async, PortalType
async def main():
# Busca assíncrona em vários portais, cada um com sua config
datasets = await search_data_async("education", portal=[
{"portal": "dados_gov_br", "api_key": "SUA_CHAVE_BR"},
"data_gov_uk",
])
# Recuperar dataset individual
dataset = await get_dataset_async("abc-123", portal=PortalType.DATA_GOUV_FR)
# Baixar e parsear dados
result = await fetch_dataset_data_async("abc-123", portal=PortalType.DATA_GOUV_FR)
asyncio.run(main())
Classe Hipolita
Para quem prefere orientação a objetos, as mesmas operações estão disponíveis como métodos estáticos:
from hlib.core import Hipolita
from hlib import PortalType
datasets = Hipolita.search_data("climate", portal=PortalType.DATA_GOV_UK)
dataset = Hipolita.get_dataset("id-123", portal=PortalType.DATA_GOV_UK)
result = Hipolita.fetch_dataset_data("id-123", portal=PortalType.DATA_GOV_UK)
Modelo de Dados
Dataset
Representa um conjunto de dados com metadados normalizados de qualquer portal.
| Campo | Tipo | Descrição |
|---|---|---|
id |
str |
Identificador único no portal de origem |
title |
str | None |
Título do dataset |
description |
str | None |
Descrição textual |
resources |
list[Resource] |
Arquivos/endpoints disponíveis |
tags |
list[str] |
Palavras-chave / categorias |
organization |
str | None |
Organização publicadora |
license |
str | None |
Licença de uso |
source_portal |
str | None |
Portal de origem |
Resource
Representa um arquivo ou endpoint de dados dentro de um dataset.
| Campo | Tipo | Descrição |
|---|---|---|
id |
str |
Identificador do recurso |
name |
str | None |
Nome do arquivo/recurso |
format |
str | None |
Formato (CSV, JSON, XML, etc.) |
url |
str | None |
URL de download |
DataFrameWithMeta
Retornado por fetch_dataset_data(). Combina dados tabulares com metadados.
| Campo | Tipo | Descrição |
|---|---|---|
df |
pd.DataFrame |
Dados parseados (vazio se não parseável) |
meta |
dict |
Metadados: title, format, resource_url, resource_links |
Arquitetura
hlib/
├── __init__.py # Exports públicos
├── core.py # API principal (search, get_dataset, fetch_dataset_data)
├── types.py # Dataset, Resource, DataFrameWithMeta, PortalType
└── data_recovery/
├── interfaces/
│ ├── adapter.py # DataAdapter (ABC)
│ └── portal.py # Portal (ABC) + fetch_dataset_data (concreto)
├── adapters/
│ ├── ckan_adapter.py # Adaptador CKAN v3 (UK, US, CH, FI, AU)
│ └── api_adapter.py # Adaptador REST genérico (BR, FR, ES, SG, IN)
└── portals/
├── portal_dados_abertos_br.py
├── portal_data_gov_us.py
├── portal_data_gov_uk.py
├── portal_opendata_swiss.py
├── portal_avoindata_fi.py
├── portal_data_gov_au.py
├── portal_data_gouv_fr.py
├── portal_datos_gob_es.py
├── portal_data_gov_sg.py
└── portal_data_gov_in.py
A arquitetura segue o padrão Strategy: cada portal implementa a lógica de mapeamento de endpoints e campos, delegando operações HTTP a um adaptador compartilhado (CkanAdapter ou ApiAdapter).
Desenvolvimento e Testes
Pré-requisitos
- Python 3.10+
- Poetry (gerenciador de dependências)
Setup
git clone https://github.com/matheus-erthal/hlib.git
cd hlib
poetry install
Executando Testes
poetry run pytest
A suíte de testes inclui 51 testes cobrindo:
- Conectividade e parsing de resposta de cada adaptador (CKAN, API genérica)
- Busca (
search()) e recuperação individual (get_dataset()) em todos os 10 portais — 9 deles via cassette de resposta real (tests/test_cassettes.py), o BR (que exigeapi_keyprópria) via mock sintético - Download e parse de dados (
fetch_dataset_data()) com CSV, JSON, recursos não parseáveis - Integração via
core.py(funções síncronas e assíncronas)
A suíte por padrão não faz nenhuma chamada de rede: os testes que validam o formato de resposta de cada portal (tests/test_cassettes.py) reproduzem respostas reais previamente capturadas, sem depender da disponibilidade dos portais no momento do teste. São esses testes que gateiam o CI e a publicação no PyPI.
Testes de Integração (APIs Reais)
Além da suíte padrão, existem testes que fazem requisições HTTP reais aos portais, para validar que os endpoints ainda estão funcionais. Eles não rodam com pytest puro — só manualmente:
poetry run pytest -m live -v
⚠️ Estes testes fazem requisições HTTP reais e podem falhar por indisponibilidade temporária dos portais.
Toda vez que um teste live passa, ele grava a resposta real do portal em tests/cassettes/ e atualiza a data de validação abaixo — essas cassettes são o que tests/test_cassettes.py reproduz por padrão.
Status de Validação ao Vivo
Data da última execução bem-sucedida de pytest -m live, por cassette:
| Cassette | Portal | Última validação |
|---|---|---|
| data_gov_us_search | data.gov (EUA) 🇺🇸 | 2026-07-20 |
| data_gov_us_get_dataset | data.gov (EUA) 🇺🇸 | 2026-07-20 |
| data_gov_uk_search | data.gov.uk (Reino Unido) 🇬🇧 | 2026-07-20 |
| data_gov_uk_get_dataset | data.gov.uk (Reino Unido) 🇬🇧 | 2026-07-20 |
| opendata_swiss_search | opendata.swiss (Suíça) 🇨🇭 | 2026-07-20 |
| opendata_swiss_get_dataset | opendata.swiss (Suíça) 🇨🇭 | 2026-07-20 |
| avoindata_fi_search | avoindata.fi (Finlândia) 🇫🇮 | 2026-07-20 |
| avoindata_fi_get_dataset | avoindata.fi (Finlândia) 🇫🇮 | 2026-07-20 |
| data_gov_au_search | data.gov.au (Austrália) 🇦🇺 | 2026-07-20 |
| data_gov_au_get_dataset | data.gov.au (Austrália) 🇦🇺 | 2026-07-20 |
| data_gouv_fr_search | data.gouv.fr (França) 🇫🇷 | 2026-07-20 |
| data_gouv_fr_get_dataset | data.gouv.fr (França) 🇫🇷 | 2026-07-20 |
| datos_gob_es_search | datos.gob.es (Espanha) 🇪🇸 | nunca validado |
| datos_gob_es_get_dataset | datos.gob.es (Espanha) 🇪🇸 | nunca validado |
| data_gov_sg_search | data.gov.sg (Singapura) 🇸🇬 | 2026-07-20 |
| data_gov_sg_get_dataset | data.gov.sg (Singapura) 🇸🇬 | 2026-07-20 |
| data_gov_in_search | data.gov.in (Índia) 🇮🇳 | 2026-07-20 |
| data_gov_in_get_dataset | data.gov.in (Índia) 🇮🇳 | 2026-07-20 |
dados.gov.brfica fora dessa tabela: exigeapi_keyprópria, então não há como validar automaticamente contra a API real neste repositório.
data.gov(EUA) migrou da API clássica do CKAN para a Catalog API v4 (DCAT-US), que não tem endpoint de busca por ID. O caso comum — pedirget_dataset()de um dataset que já apareceu em umsearch()anterior na mesma instância dePortalDataGovUS— funciona normalmente, resolvido por um cache local, sem chamada de rede extra. Só para um ID "frio" (que não veio de umsearch()prévio nesta instância) é queget_dataset()cai num fallback paginando/searchaté achar oidentifier, sem garantia de encontrar. Desative esse fallback comPortalDataGovUS(id_lookup_fallback=False)se preferir sempreNonenesse caso frio em vez de um scan potencialmente longo.
Licença
Este projeto é distribuído sob a 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
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 hipolita-0.3.1.tar.gz.
File metadata
- Download URL: hipolita-0.3.1.tar.gz
- Upload date:
- Size: 21.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.4.1 CPython/3.11.15 Linux/6.17.0-1020-azure
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
30a0c5382c3fda2ff807c7a7ebdc1b618708884c729c8ed4a7b9b793b6265b01
|
|
| MD5 |
4aa71dd92fb7ae490814ea4cf10ffc5a
|
|
| BLAKE2b-256 |
e62ee6f5db31460602e3fd6b6579de4069163969200d106ce9c63ff6f4e6dd92
|
File details
Details for the file hipolita-0.3.1-py3-none-any.whl.
File metadata
- Download URL: hipolita-0.3.1-py3-none-any.whl
- Upload date:
- Size: 27.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.4.1 CPython/3.11.15 Linux/6.17.0-1020-azure
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9ebb474d5870a28f1136cfe30b8a361f06597ea3978ce7ea9839b6f0e60774b6
|
|
| MD5 |
4faeebf30e031cd1b6f4ea419b03b134
|
|
| BLAKE2b-256 |
f4c381e79128e6bd081c940c62888fa8944eed1b99ba36a216a959dd71fa8350
|