Skip to main content

This project is an implementation of the Hipolita framework

Project description

HLib

Build PyPI License

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 ela search()/get_dataset() levantam ValueError. Solicite em dados.gov.br.
  • EUA (data.gov) — opcional para uso leve: sem api_key, usa a DEMO_KEY pú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 exige api_key pró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.br fica fora dessa tabela: exige api_key pró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 — pedir get_dataset() de um dataset que já apareceu em um search() anterior na mesma instância de PortalDataGovUS — funciona normalmente, resolvido por um cache local, sem chamada de rede extra. Só para um ID "frio" (que não veio de um search() prévio nesta instância) é que get_dataset() cai num fallback paginando /search até achar o identifier, sem garantia de encontrar. Desative esse fallback com PortalDataGovUS(id_lookup_fallback=False) se preferir sempre None nesse 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

hipolita-0.3.1.tar.gz (21.5 kB view details)

Uploaded Source

Built Distribution

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

hipolita-0.3.1-py3-none-any.whl (27.9 kB view details)

Uploaded Python 3

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

Hashes for hipolita-0.3.1.tar.gz
Algorithm Hash digest
SHA256 30a0c5382c3fda2ff807c7a7ebdc1b618708884c729c8ed4a7b9b793b6265b01
MD5 4aa71dd92fb7ae490814ea4cf10ffc5a
BLAKE2b-256 e62ee6f5db31460602e3fd6b6579de4069163969200d106ce9c63ff6f4e6dd92

See more details on using hashes here.

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

Hashes for hipolita-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 9ebb474d5870a28f1136cfe30b8a361f06597ea3978ce7ea9839b6f0e60774b6
MD5 4faeebf30e031cd1b6f4ea419b03b134
BLAKE2b-256 f4c381e79128e6bd081c940c62888fa8944eed1b99ba36a216a959dd71fa8350

See more details on using hashes here.

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