Pular para conteúdo

Convenções de Armazenamento — Fetchers

Esta página cobre a perspectiva do usuário final: como os arquivos são nomeados, como as pastas são organizadas e como a flag -o funciona. Para a perspectiva do contribuidor (como implementar essas convenções num novo fetcher), veja Padronização de CLI.

Este documento define os padrões de nomenclatura de arquivos, estrutura de pastas e interface CLI adotados por todos os pacotes fetcher da Quantilica.


Nomenclatura de Arquivos

O nome de cada arquivo baixado incorpora um timestamp extraído do servidor de origem (cabeçalho Last-Modified ou equivalente). A função stamp_filename() de quantilica.core.storage implementa o padrão.

Formato

{base}@{timestamp}.{ext}

O separador entre a base e o timestamp é sempre @. A base codifica o conjunto de dados e a partição; o timestamp indica quando o arquivo foi publicado na origem, não quando foi baixado.

Precisão do timestamp

Precisão Formato Quando usar
date (padrão) YYYYMMDD Fontes com granularidade diária
datetime YYYYMMDDTHHMMSS Fontes com múltiplas versões no mesmo dia

Quando o servidor não retorna timestamp, o arquivo é salvo sem @ — sem inventar uma data.

Exemplos por pacote

Pacote Exemplo de nome
comex-fetcher [email protected]
datasus-fetcher [email protected]
inmet-fetcher [email protected]
pdet-fetcher [email protected]
rtn-fetcher [email protected]
tesouro-direto-fetcher taxas-dos-titulos-ofertados-pelo-tesouro-direto@20240315T101530.csv

Implementação

from quantilica.core.storage import stamp_filename

# Precisão date (padrão)
stamp_filename("exp_2023", "csv", date(2024, 3, 15))
# → "[email protected]"

# Precisão datetime
stamp_filename("rtn", "xlsx", datetime(2024, 3, 15, 10, 15), precision="datetime")
# → "[email protected]"

# Sem timestamp
stamp_filename("rtn", "xlsx", None)
# → "rtn.xlsx"

Gramática canônica de particionamento (format_partition_token)

Quando um conjunto de dados é distribuído em múltiplos arquivos por recorte temporal ou geográfico, o nome base ({base}) incorpora o token de partição separado do identificador do dataset ({slug}) por sublinhado (_), construído via build_stamped_filename() e format_partition_token:

{slug}_{partition_token}@{timestamp}.{ext}
Recorte da partição Gramática do token (format_partition_token) Exemplo de arquivo bruto
Sem partição (arquivo único) (omitido) [email protected]
Anual (year) {year} (YYYY) [email protected]
Mensal (year, month) {year}-{month:02d} ou {year}{month:02d} [email protected]
Semestral (year, semester) {year}-{semester:02d} ou {year}-S{semester} [email protected]
Temporal + UF / Região {periodo}-{uf_ou_regiao} (minúsculo) [email protected], [email protected]

Posicionamento de @YYYYMMDD antes de extensões compostas

O carimbo @YYYYMMDD (ou @YYYYMMDDTHHMMSS) posiciona-se sempre imediatamente antes da extensão completa do arquivo — inclusive quando o arquivo possui extensão composta de compressão (como .csv.gz, .tar.gz, .json.zst):

Na etapa de conversão para o Lake Hive, a função file_key() de quantilica.core.lake remove iterativamente todas as extensões brutas da lista canônica (.gz, .csv, .zip, .7z, .tar, etc.) e, ao final, descarta o sufixo @YYYYMMDD, restituindo de forma determinística a chave limpa cotacoes_2024 para gerar cotacoes_2024.parquet.

Preservação histórica e imutabilidade da camada bruta ("nada se apaga")

Um objetivo central da Quantilica é possibilitar e facilitar o arquivamento e a preservação histórica de dados públicos brutos. O padrão {base}@{timestamp}.{ext} garante que o diretório bruto funcione como um acervo imutável e append-only:

  • Coexistência de revisões: quando um órgão público retifica ou republica um arquivo histórico com uma nova data de modificação, o coletor grava um novo arquivo ao lado do existente (ex.: [email protected] e [email protected]), cada um com seu próprio .manifest.json. Nada se apaga e nenhuma revisão anterior é sobrescrita.
  • Seleção determinística para o Lake (select_current): enquanto a camada bruta preserva todas as safras históricas já publicadas, a função select_current() de quantilica.core.lake inspeciona as versões disponíveis para cada file_key() e elege deterministicamente a revisão vigente (maior @timestamp) para alimentar a conversão do Lake Hive.
flowchart LR
    subgraph Raw ["Camada Bruta (/data/<fonte>)"]
        F["{dataset_id}/{slug}_{particao}@{YYYYMMDD}.{ext}"]
        M["{dataset_id}/{slug}_{particao}@{YYYYMMDD}.{ext}.manifest.json"]
        F --- M
    end

    subgraph Key ["Extração de Identidade (quantilica.core.lake)"]
        FK["file_key() remove .{ext} compostas e @{YYYYMMDD}"]
    end

    subgraph Lake ["Camada Lake Hive ($QUANTILICA_LAKE_DIR)"]
        P["<source_id>/<dataset_id>/<k1>=<v1>/{slug}_{particao}.parquet"]
        D["<source_id>/<dataset_id>/_dataset.json"]
    end

    Raw --> Key --> Lake

Estrutura de Pastas

Os arquivos são organizados em pastas diretamente nomeadas pelo dataset_id, sem camada intermediária de categoria (sem raw//processed//docs/). Esta é a estrutura adotada por todos os fetchers e implementada pelo método BaseDataRepository.dataset_path() do quantilica-core.

Princípio

{output}/
├── {dataset_id}/
│   ├── {partição}/      ← opcional; usada quando há agrupamento temporal ou geográfico
│   │   └── [email protected]
│   └── [email protected]
└── ...

O diretório raiz ({output}) é o único caminho fornecido pelo usuário. A estrutura interna é de responsabilidade exclusiva do pacote.

API do quantilica-core

from quantilica.core.storage import BaseDataRepository

class FooRepository(BaseDataRepository):
    def file_path(self, dataset_id: str, filename: str) -> Path:
        return self.dataset_path(dataset_id, filename)
        # → {root}/{dataset_id}/{filename}

Categorias adicionais (documentação, dados processados, etc.) são responsabilidade do fetcher — use self.storage.path_for(...) diretamente.

Decisão de subdiretório por ano ou competência (subdir_by_year=True vs False)

O DataRepository (quantilica.cli.sdk) suporta duas estratégias para organizar os arquivos dentro de {output}/{dataset_id}/:

Configuração Layout em disco Quando adotar Exemplos
subdir_by_year=False (padrão) {output}/{dataset_id}/{slug}_{particao}@{YYYYMMDD}.{ext} Datasets com até algumas centenas de arquivos (partições anuais, semestrais ou mensais nacionais) comex-fetcher, cvm-fetcher, anp-fetcher, anac-fetcher, tesouro-direto-fetcher
subdir_by_year=True {output}/{dataset_id}/{ano_ou_competencia}/{slug}_{particao}@{YYYYMMDD}.{ext} Datasets massivamente fragmentados (ex.: competência mensal × 27 UFs = 324 arquivos por ano), evitando diretórios planos com dezenas de milhares de inodes datasus-fetcher, pdet-fetcher (RAIS/CAGED particionados)

Manifesto de proveniência v2 (DownloadManifest e dataset_id)

Todo arquivo bruto salvo em {output}/{dataset_id}/ é acompanhado de um arquivo sidecar {arquivo}.manifest.json no schema v2 (MANIFEST_VERSION = 2 de quantilica.core.manifests).

O manifesto registra obrigatoriamente o dataset_id canônico ao lado do source_id, permitindo auditoria de proveniência e vinculação direta com o descritor _dataset.json do Lake Hive, além dos 5 grupos opcionais de enriquecimento da v2 (source_meta, fingerprint, lineage, quality e execution — veja a especificação completa em Proveniência & Manifestos):

{
  "dataset_id": "exp",
  "fetched_at": "2026-10-20T14:22:10Z",
  "manifest_version": 2,
  "path": "/data/comex/exp/[email protected]",
  "producer": "comex-fetcher",
  "producer_version": "0.4.0",
  "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
  "size_bytes": 184520910,
  "source_id": "comex",
  "source_meta": {
    "etag": "\"65f41a-2b10c\"",
    "last_modified": "Fri, 15 Mar 2024 12:00:00 GMT"
  },
  "url": "https://balanca.economia.gov.br/balanca/bd/comexstat-bd/ncm/EXP_2024.csv"
}

Exemplos por pacote

comex-fetcher

{output}/
├── exp/
│   └── [email protected]
├── imp/
│   └── [email protected]
├── exp-mun/
├── imp-mun/
├── auxiliary-tables/
│   └── [email protected]
├── repetro/
└── validacao/

datasus-fetcher

{output}/
├── sih-rd/
│   ├── 202001/
│   │   └── [email protected]
│   └── 202002/
├── sinasc-dn/
│   └── 2023/
│       └── [email protected]
├── _documentacao/
│   ├── sih/
│   │   └── [email protected]
│   └── sinasc/
└── _auxiliar/
    └── sih/
        └── [email protected]

Documentação e tabelas auxiliares são agrupadas pelo sistema (ex: sih, cnes), não pelo subsistema (ex: sih-rd, cnes-dc), pois um mesmo conjunto de documentos cobre todos os subsistemas de um sistema. O prefixo _ faz essas pastas aparecerem antes das pastas de dados em qualquer ordenação alfabética e evita nomes reservados do Windows (como aux).

Para a estrutura detalhada de todos os demais pacotes (inmet-fetcher, pdet-fetcher, rtn-fetcher, tesouro-direto-fetcher), veja a seção de exemplos em Padronização de CLI.


Interface CLI

A convenção é expor o diretório de saída pelo argumento -o / --output. Nos fetchers clássicos há um valor padrão /data/<fonte>; nos fetchers novos com catálogo declarativo o destino é informado por comando — consulte quantilica <fonte> --help.

Para especificações detalhadas sobre a implementação desse argumento, as opções do parser e regras adicionais de interface, consulte o guia de Padronização de CLI.

Padrões de Diretório por Pacote

Abaixo estão definidos os diretórios de saída padrão (default de --output) adotados por cada fetcher:

Pacote Diretório Padrão (--output)
anac-fetcher /data/anac
anp-fetcher /data/anp
bcb-sgs-fetcher /data/bcb-sgs
comex-fetcher /data/comex
cvm-fetcher /data/cvm
datasus-fetcher /data/datasus
inep-fetcher /data/inep
inmet-fetcher /data/inmet
pdet-fetcher /data/pdet
rfb-cnpj-fetcher /data/rfb-cnpj
rtn-fetcher /data/rtn
sidra-fetcher /data/sidra
tesouro-direto-fetcher /data/tesouro-direto
tse-fetcher /data/tse

Os fetchers baseados em FetcherApp derivam o padrão do nome do pacote (/data/<fonte>). O -o/--output sobrescreve em qualquer um.


Atualizado em: 28 de setembro de 2026