agrobr 0.1.2__tar.gz → 0.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agrobr-0.5.0/.github/workflows/docs.yml +42 -0
- agrobr-0.5.0/.gitignore +27 -0
- agrobr-0.5.0/CHANGELOG.md +180 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/PKG-INFO +12 -12
- {agrobr-0.1.2 → agrobr-0.5.0}/README.md +11 -11
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/__init__.py +3 -2
- agrobr-0.5.0/agrobr/benchmark/__init__.py +343 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/cache/policies.py +3 -8
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/cepea/api.py +87 -30
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/cepea/client.py +0 -7
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/cli.py +141 -5
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/conab/api.py +72 -6
- agrobr-0.5.0/agrobr/config.py +137 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/constants.py +1 -2
- agrobr-0.5.0/agrobr/contracts/__init__.py +186 -0
- agrobr-0.5.0/agrobr/contracts/cepea.py +80 -0
- agrobr-0.5.0/agrobr/contracts/conab.py +181 -0
- agrobr-0.5.0/agrobr/contracts/ibge.py +146 -0
- agrobr-0.5.0/agrobr/export.py +251 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/health/__init__.py +10 -0
- agrobr-0.5.0/agrobr/health/doctor.py +321 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/http/browser.py +0 -9
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/ibge/api.py +104 -25
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/ibge/client.py +5 -20
- agrobr-0.5.0/agrobr/models.py +184 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/noticias_agricolas/client.py +0 -7
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/noticias_agricolas/parser.py +0 -17
- agrobr-0.5.0/agrobr/plugins/__init__.py +205 -0
- agrobr-0.5.0/agrobr/quality.py +319 -0
- agrobr-0.5.0/agrobr/sla.py +249 -0
- agrobr-0.5.0/agrobr/snapshots.py +321 -0
- agrobr-0.5.0/agrobr/stability.py +148 -0
- agrobr-0.5.0/agrobr/validators/semantic.py +447 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/docs/advanced/resilience.md +57 -0
- agrobr-0.5.0/docs/sources/cepea.md +120 -0
- agrobr-0.5.0/docs/sources/conab.md +147 -0
- agrobr-0.5.0/docs/sources/ibge.md +156 -0
- agrobr-0.5.0/docs/sources/index.md +83 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/pyproject.toml +1 -1
- agrobr-0.5.0/tests/test_config/__init__.py +1 -0
- agrobr-0.5.0/tests/test_config/test_config.py +152 -0
- agrobr-0.5.0/tests/test_config/test_export.py +208 -0
- agrobr-0.5.0/tests/test_config/test_snapshots.py +189 -0
- agrobr-0.5.0/tests/test_contracts/__init__.py +1 -0
- agrobr-0.5.0/tests/test_contracts/test_contracts.py +208 -0
- agrobr-0.5.0/tests/test_health/__init__.py +1 -0
- agrobr-0.5.0/tests/test_health/test_doctor.py +172 -0
- agrobr-0.5.0/tests/test_models.py +175 -0
- agrobr-0.5.0/tests/test_plugins/__init__.py +1 -0
- agrobr-0.5.0/tests/test_plugins/test_plugins.py +207 -0
- agrobr-0.5.0/tests/test_plugins/test_quality.py +213 -0
- agrobr-0.5.0/tests/test_plugins/test_sla.py +149 -0
- agrobr-0.5.0/tests/test_plugins/test_stability.py +172 -0
- agrobr-0.5.0/tests/test_validators/test_semantic.py +170 -0
- agrobr-0.1.2/.gitignore +0 -2
- agrobr-0.1.2/CHANGELOG.md +0 -60
- agrobr-0.1.2/agrobr/models.py +0 -85
- {agrobr-0.1.2 → agrobr-0.5.0}/.github/workflows/health_check.yml +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/.github/workflows/publish.yml +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/.github/workflows/structure_monitor.yml +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/.github/workflows/tests.yml +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/.pre-commit-config.yaml +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/.structures/baseline.json +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/CODE_OF_CONDUCT.md +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/CONTRIBUTING.md +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/LICENSE +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/alerts/__init__.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/alerts/notifier.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/cache/__init__.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/cache/duckdb_store.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/cache/history.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/cache/migrations.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/cepea/__init__.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/cepea/parsers/__init__.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/cepea/parsers/base.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/cepea/parsers/consensus.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/cepea/parsers/detector.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/cepea/parsers/fingerprint.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/cepea/parsers/v1.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/conab/__init__.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/conab/client.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/conab/parsers/__init__.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/conab/parsers/v1.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/exceptions.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/health/checker.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/health/reporter.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/http/__init__.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/http/rate_limiter.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/http/retry.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/http/user_agents.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/ibge/__init__.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/normalize/__init__.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/normalize/dates.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/normalize/encoding.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/normalize/regions.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/normalize/units.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/noticias_agricolas/__init__.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/sync.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/telemetry/__init__.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/telemetry/collector.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/utils/__init__.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/utils/logging.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/validators/__init__.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/validators/sanity.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/agrobr/validators/structural.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/docs/advanced/troubleshooting.md +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/docs/api/cepea.md +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/docs/api/conab.md +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/docs/api/ibge.md +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/docs/index.md +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/docs/quickstart.md +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/examples/analise_soja.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/examples/pipeline_async.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/mkdocs.yml +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/scripts/alert_structure_change.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/scripts/compare_structures.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/scripts/create_workflows.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/scripts/fetch_structures.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/scripts/update_golden.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/tests/__init__.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/tests/conftest.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/tests/golden_data/cepea/soja_sample/expected.json +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/tests/golden_data/cepea/soja_sample/metadata.json +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/tests/golden_data/cepea/soja_sample/response.html +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/tests/golden_data/conab/safra_sample/expected.json +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/tests/golden_data/conab/safra_sample/metadata.json +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/tests/golden_data/conab/safra_sample/response.xlsx +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/tests/test_cepea/__init__.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/tests/test_cepea/test_api.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/tests/test_cepea/test_fingerprint.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/tests/test_cepea/test_parser.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/tests/test_conab/__init__.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/tests/test_conab/test_parser.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/tests/test_golden.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/tests/test_ibge/__init__.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/tests/test_ibge/test_api.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/tests/test_ibge/test_client.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/tests/test_noticias_agricolas/__init__.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/tests/test_noticias_agricolas/test_parser.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/tests/test_validators/__init__.py +0 -0
- {agrobr-0.1.2 → agrobr-0.5.0}/tests/test_validators/test_sanity.py +0 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
name: Deploy Docs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
pages: write
|
|
11
|
+
id-token: write
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
deploy:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
environment:
|
|
17
|
+
name: github-pages
|
|
18
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
|
|
22
|
+
- uses: actions/setup-python@v5
|
|
23
|
+
with:
|
|
24
|
+
python-version: '3.11'
|
|
25
|
+
|
|
26
|
+
- name: Install dependencies
|
|
27
|
+
run: pip install mkdocs-material mkdocstrings mkdocstrings-python
|
|
28
|
+
|
|
29
|
+
- name: Build docs
|
|
30
|
+
run: mkdocs build
|
|
31
|
+
|
|
32
|
+
- name: Setup Pages
|
|
33
|
+
uses: actions/configure-pages@v4
|
|
34
|
+
|
|
35
|
+
- name: Upload artifact
|
|
36
|
+
uses: actions/upload-pages-artifact@v3
|
|
37
|
+
with:
|
|
38
|
+
path: site
|
|
39
|
+
|
|
40
|
+
- name: Deploy to GitHub Pages
|
|
41
|
+
id: deployment
|
|
42
|
+
uses: actions/deploy-pages@v4
|
agrobr-0.5.0/.gitignore
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# Environments
|
|
7
|
+
.env
|
|
8
|
+
.venv
|
|
9
|
+
venv/
|
|
10
|
+
|
|
11
|
+
# IDE
|
|
12
|
+
.vscode/
|
|
13
|
+
.idea/
|
|
14
|
+
|
|
15
|
+
# Build
|
|
16
|
+
dist/
|
|
17
|
+
*.egg-info/
|
|
18
|
+
|
|
19
|
+
# Cache
|
|
20
|
+
.pytest_cache/
|
|
21
|
+
.mypy_cache/
|
|
22
|
+
.ruff_cache/
|
|
23
|
+
|
|
24
|
+
# Project
|
|
25
|
+
.claude/
|
|
26
|
+
agrobr_v3.txt
|
|
27
|
+
agrobr_roadmap_v2.txt
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Todas as mudanças notáveis neste projeto serão documentadas neste arquivo.
|
|
4
|
+
|
|
5
|
+
O formato é baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.0.0/),
|
|
6
|
+
e este projeto adere ao [Versionamento Semântico](https://semver.org/lang/pt-BR/).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.5.0] - 2026-02-04
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- **Plugin System** - Arquitetura extensível para fontes e validadores
|
|
14
|
+
- `SourcePlugin` - Interface para novas fontes de dados
|
|
15
|
+
- `ParserPlugin` - Interface para parsers customizados
|
|
16
|
+
- `ExporterPlugin` - Interface para exportadores customizados
|
|
17
|
+
- `ValidatorPlugin` - Interface para validadores customizados
|
|
18
|
+
- `register()`, `get_plugin()`, `list_plugins()` - Gerenciamento de plugins
|
|
19
|
+
- **API Stability Decorators** - Marcadores de estabilidade de API
|
|
20
|
+
- `@stable(since="x.y.z")` - Marca API como estável
|
|
21
|
+
- `@experimental(since="x.y.z")` - Marca API como experimental
|
|
22
|
+
- `@deprecated(since, removed_in, replacement)` - Marca API como deprecated
|
|
23
|
+
- `@internal` - Marca API como interna (não pública)
|
|
24
|
+
- `list_stable_apis()`, `list_experimental_apis()`, `list_deprecated_apis()`
|
|
25
|
+
- **SLA Documentado** - Contratos de nível de serviço por fonte
|
|
26
|
+
- `SourceSLA` - Definição de SLA com tier, freshness, latency, availability
|
|
27
|
+
- `CEPEA_SLA` - Tier CRITICAL, atualização diária 18h, 99% uptime
|
|
28
|
+
- `CONAB_SLA` - Tier STANDARD, atualização mensal, 98% uptime
|
|
29
|
+
- `IBGE_SLA` - Tier STANDARD, varia por pesquisa
|
|
30
|
+
- `get_sla()`, `list_slas()`, `get_sla_summary()`
|
|
31
|
+
- **Certificação de Qualidade** - Sistema de certificação de dados
|
|
32
|
+
- `QualityLevel` - GOLD, SILVER, BRONZE, UNCERTIFIED
|
|
33
|
+
- `QualityCheck` - Check individual com status e detalhes
|
|
34
|
+
- `QualityCertificate` - Certificado completo com score e validade
|
|
35
|
+
- `certify(df)` - Executa checks (completeness, duplicates, schema, freshness, range)
|
|
36
|
+
- `quick_check(df)` - Retorna (level, score) rapidamente
|
|
37
|
+
|
|
38
|
+
## [0.4.0] - 2026-02-04
|
|
39
|
+
|
|
40
|
+
### Added
|
|
41
|
+
- **Modo Determinístico** - Reprodutibilidade absoluta para backtests
|
|
42
|
+
- `agrobr.set_mode("deterministic", snapshot="2025-01-01")`
|
|
43
|
+
- `agrobr.configure()` para opções globais
|
|
44
|
+
- `agrobr.get_config()` para consultar configuração atual
|
|
45
|
+
- `agrobr.reset_config()` para resetar ao padrão
|
|
46
|
+
- **Sistema de Snapshots** - Gerenciamento de versões de dados
|
|
47
|
+
- `create_snapshot()` - Cria snapshot dos dados atuais
|
|
48
|
+
- `load_from_snapshot()` - Carrega dados de um snapshot
|
|
49
|
+
- `list_snapshots()` / `delete_snapshot()` - Gerenciamento
|
|
50
|
+
- CLI: `agrobr snapshot create/list/delete/use`
|
|
51
|
+
- **Export Auditável** - Formatos com metadados de proveniência
|
|
52
|
+
- `export_parquet()` - Parquet com metadata embutido
|
|
53
|
+
- `export_csv()` - CSV com arquivo sidecar .meta.json
|
|
54
|
+
- `export_json()` - JSON com metadados opcionais
|
|
55
|
+
- `verify_export()` - Verificação de integridade
|
|
56
|
+
|
|
57
|
+
## [0.3.0] - 2026-02-04
|
|
58
|
+
|
|
59
|
+
### Added
|
|
60
|
+
- **Stability Contracts** - Garantias formais de schema para todas as fontes
|
|
61
|
+
- `CEPEA_INDICADOR_V1` - Contrato para indicadores de preço CEPEA
|
|
62
|
+
- `CONAB_SAFRA_V1` - Contrato para dados de safra CONAB
|
|
63
|
+
- `CONAB_BALANCO_V1` - Contrato para balanço oferta/demanda CONAB
|
|
64
|
+
- `IBGE_PAM_V1` - Contrato para dados PAM do IBGE
|
|
65
|
+
- `IBGE_LSPA_V1` - Contrato para dados LSPA do IBGE
|
|
66
|
+
- `contract.validate(df)` - Validação automática contra contrato
|
|
67
|
+
- `contract.to_markdown()` - Documentação automática
|
|
68
|
+
- **Validação Semântica** - Verificações avançadas de qualidade
|
|
69
|
+
- Validação de preços positivos
|
|
70
|
+
- Validação de faixas de produtividade por cultura
|
|
71
|
+
- Detecção de anomalias em variação diária (>20%)
|
|
72
|
+
- Consistência de sequência de datas
|
|
73
|
+
- Consistência de áreas (colhida <= plantada)
|
|
74
|
+
- Validação de formato de safra
|
|
75
|
+
- `validate_semantic(df)` - Executa todas as regras
|
|
76
|
+
- `get_validation_summary(df)` - Resumo das violações
|
|
77
|
+
- **Benchmark Suite** - Ferramentas para medição de performance
|
|
78
|
+
- `benchmark_async()` / `benchmark_sync()` - Benchmark de funções
|
|
79
|
+
- `run_api_benchmarks()` - Benchmark das APIs
|
|
80
|
+
- `run_contract_benchmarks()` - Benchmark de validação de contratos
|
|
81
|
+
- `run_semantic_benchmarks()` - Benchmark de validação semântica
|
|
82
|
+
|
|
83
|
+
### Changed
|
|
84
|
+
- Changelog reestruturado seguindo Keep a Changelog
|
|
85
|
+
|
|
86
|
+
## [0.2.0] - 2026-02-04
|
|
87
|
+
|
|
88
|
+
### Added
|
|
89
|
+
- **`agrobr doctor`** - Comando CLI para diagnóstico do sistema
|
|
90
|
+
- Verificação de conectividade das fontes
|
|
91
|
+
- Estatísticas do cache (tamanho, registros, por fonte)
|
|
92
|
+
- Status de configuração
|
|
93
|
+
- Output JSON (`--json`) e formatado Rich
|
|
94
|
+
- **Parâmetro `return_meta`** - Suporte a data lineage em todas as APIs
|
|
95
|
+
- `cepea.indicador(return_meta=True)` retorna `(DataFrame, MetaInfo)`
|
|
96
|
+
- `conab.safras(return_meta=True)` retorna `(DataFrame, MetaInfo)`
|
|
97
|
+
- `ibge.pam(return_meta=True)` retorna `(DataFrame, MetaInfo)`
|
|
98
|
+
- `ibge.lspa(return_meta=True)` retorna `(DataFrame, MetaInfo)`
|
|
99
|
+
- **Classe `MetaInfo`** - Metadados de proveniência e rastreabilidade
|
|
100
|
+
- Informações da fonte (nome, URL, método)
|
|
101
|
+
- Timing (duração fetch, duração parse)
|
|
102
|
+
- Status do cache (from_cache, cache_key, expires_at)
|
|
103
|
+
- Integridade do conteúdo (hash SHA256, tamanho)
|
|
104
|
+
- Versões (agrobr, parser, schema, python)
|
|
105
|
+
- `to_dict()` / `to_json()` para serialização
|
|
106
|
+
- `verify_hash(df)` para verificação de integridade
|
|
107
|
+
- **Documentação** - Guias de proveniência e resiliência
|
|
108
|
+
- `docs/sources/cepea.md` - Documentação da fonte CEPEA
|
|
109
|
+
- `docs/sources/conab.md` - Documentação da fonte CONAB
|
|
110
|
+
- `docs/sources/ibge.md` - Documentação da fonte IBGE
|
|
111
|
+
- `docs/advanced/resilience.md` - Documentação de resiliência
|
|
112
|
+
|
|
113
|
+
### Changed
|
|
114
|
+
- `MetaInfo` exportado do pacote principal
|
|
115
|
+
|
|
116
|
+
## [0.1.2] - 2026-02-04
|
|
117
|
+
|
|
118
|
+
### Changed
|
|
119
|
+
- **Smart TTL** para cache CEPEA - expira às 18:00 (horário de atualização CEPEA)
|
|
120
|
+
- Reduz requests desnecessários em ~90%
|
|
121
|
+
|
|
122
|
+
## [0.1.1] - 2026-02-04
|
|
123
|
+
|
|
124
|
+
### Fixed
|
|
125
|
+
- Browser fallback desabilitado para CEPEA (Cloudflare bloqueia)
|
|
126
|
+
- CEPEA agora vai direto para Notícias Agrícolas, evitando timeout
|
|
127
|
+
|
|
128
|
+
## [0.1.0] - 2026-02-04
|
|
129
|
+
|
|
130
|
+
### Added
|
|
131
|
+
- **CEPEA**: Indicadores de preços agrícolas (soja, milho, boi, café, algodão, trigo)
|
|
132
|
+
- Fallback automático para Notícias Agrícolas quando CEPEA bloqueado
|
|
133
|
+
- Acumulação progressiva de histórico no DuckDB
|
|
134
|
+
- **CONAB**: Dados de safras e balanço oferta/demanda
|
|
135
|
+
- Parser para planilhas XLSX do boletim de safras
|
|
136
|
+
- Suporte a todos os produtos principais (soja, milho, arroz, feijão, etc.)
|
|
137
|
+
- **IBGE**: Integração com API SIDRA
|
|
138
|
+
- PAM (Produção Agrícola Municipal) - dados anuais
|
|
139
|
+
- LSPA (Levantamento Sistemático) - estimativas mensais
|
|
140
|
+
- **Cache**: Sistema de cache com DuckDB
|
|
141
|
+
- Separação entre cache volátil e histórico permanente
|
|
142
|
+
- TTL configurável por fonte
|
|
143
|
+
- Acumulação progressiva de dados
|
|
144
|
+
- **HTTP**: Cliente robusto com resiliência
|
|
145
|
+
- Retry com exponential backoff
|
|
146
|
+
- Rate limiting por fonte
|
|
147
|
+
- User-agent rotativo
|
|
148
|
+
- Fallback para Playwright quando necessário
|
|
149
|
+
- **CLI**: Interface de linha de comando completa
|
|
150
|
+
- Comandos para CEPEA, CONAB e IBGE
|
|
151
|
+
- Exportação em CSV, JSON e Parquet
|
|
152
|
+
- **Validação**: Sistema de validação multinível
|
|
153
|
+
- Pydantic v2 para validação de tipos
|
|
154
|
+
- Validação estatística (sanity checks)
|
|
155
|
+
- Fingerprinting de layout para detecção de mudanças
|
|
156
|
+
- **Monitoramento**: Health checks e alertas
|
|
157
|
+
- Health check por fonte
|
|
158
|
+
- Alertas multi-canal (Slack, Discord, Email)
|
|
159
|
+
- Monitoramento de estrutura
|
|
160
|
+
- **Suporte Polars**: Todas as APIs suportam `as_polars=True`
|
|
161
|
+
- **Testes**: 96 testes passando (~80% cobertura)
|
|
162
|
+
- **CI/CD**: GitHub Actions configurados
|
|
163
|
+
- Testes automatizados
|
|
164
|
+
- Health check diário
|
|
165
|
+
- Monitoramento de estrutura
|
|
166
|
+
|
|
167
|
+
### Technical Details
|
|
168
|
+
- Python 3.11+ required
|
|
169
|
+
- Async-first design com sync wrapper
|
|
170
|
+
- Type hints completos
|
|
171
|
+
- Logging estruturado com structlog
|
|
172
|
+
|
|
173
|
+
[Unreleased]: https://github.com/bruno-portfolio/agrobr/compare/v0.5.0...HEAD
|
|
174
|
+
[0.5.0]: https://github.com/bruno-portfolio/agrobr/compare/v0.4.0...v0.5.0
|
|
175
|
+
[0.4.0]: https://github.com/bruno-portfolio/agrobr/compare/v0.3.0...v0.4.0
|
|
176
|
+
[0.3.0]: https://github.com/bruno-portfolio/agrobr/compare/v0.2.0...v0.3.0
|
|
177
|
+
[0.2.0]: https://github.com/bruno-portfolio/agrobr/compare/v0.1.2...v0.2.0
|
|
178
|
+
[0.1.2]: https://github.com/bruno-portfolio/agrobr/compare/v0.1.1...v0.1.2
|
|
179
|
+
[0.1.1]: https://github.com/bruno-portfolio/agrobr/compare/v0.1.0...v0.1.1
|
|
180
|
+
[0.1.0]: https://github.com/bruno-portfolio/agrobr/releases/tag/v0.1.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agrobr
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Summary: Dados agrícolas brasileiros em uma linha de código
|
|
5
5
|
Project-URL: Homepage, https://github.com/bruno-portfolio/agrobr
|
|
6
6
|
Project-URL: Documentation, https://agrobr.dev
|
|
@@ -201,16 +201,16 @@ agrobr health --all
|
|
|
201
201
|
|
|
202
202
|
## Diferenciais
|
|
203
203
|
|
|
204
|
-
-
|
|
205
|
-
-
|
|
206
|
-
-
|
|
207
|
-
-
|
|
208
|
-
-
|
|
209
|
-
-
|
|
210
|
-
-
|
|
211
|
-
-
|
|
212
|
-
-
|
|
213
|
-
-
|
|
204
|
+
- **Async-first** para pipelines de alta performance
|
|
205
|
+
- **Cache inteligente** com DuckDB (analytics nativo)
|
|
206
|
+
- **Histórico permanente** - acumula dados automaticamente
|
|
207
|
+
- **Suporte pandas + polars**
|
|
208
|
+
- **Validação com Pydantic v2**
|
|
209
|
+
- **Validação estatística** de sanidade (detecta anomalias)
|
|
210
|
+
- **Fingerprinting de layout** para detecção proativa de mudanças
|
|
211
|
+
- **Alertas multi-canal** (Slack, Discord, Email)
|
|
212
|
+
- **CLI completo** para debug e automação
|
|
213
|
+
- **Fallback automático** entre fontes
|
|
214
214
|
|
|
215
215
|
## Como Funciona
|
|
216
216
|
|
|
@@ -226,7 +226,7 @@ Consultas a períodos antigos são instantâneas (cache). Apenas dados recentes
|
|
|
226
226
|
|
|
227
227
|
## Documentação
|
|
228
228
|
|
|
229
|
-
|
|
229
|
+
[Documentação completa](https://bruno-portfolio.github.io/agrobr/)
|
|
230
230
|
|
|
231
231
|
- [Guia Rápido](https://bruno-portfolio.github.io/agrobr/quickstart/)
|
|
232
232
|
- [API CEPEA](https://bruno-portfolio.github.io/agrobr/api/cepea/)
|
|
@@ -132,16 +132,16 @@ agrobr health --all
|
|
|
132
132
|
|
|
133
133
|
## Diferenciais
|
|
134
134
|
|
|
135
|
-
-
|
|
136
|
-
-
|
|
137
|
-
-
|
|
138
|
-
-
|
|
139
|
-
-
|
|
140
|
-
-
|
|
141
|
-
-
|
|
142
|
-
-
|
|
143
|
-
-
|
|
144
|
-
-
|
|
135
|
+
- **Async-first** para pipelines de alta performance
|
|
136
|
+
- **Cache inteligente** com DuckDB (analytics nativo)
|
|
137
|
+
- **Histórico permanente** - acumula dados automaticamente
|
|
138
|
+
- **Suporte pandas + polars**
|
|
139
|
+
- **Validação com Pydantic v2**
|
|
140
|
+
- **Validação estatística** de sanidade (detecta anomalias)
|
|
141
|
+
- **Fingerprinting de layout** para detecção proativa de mudanças
|
|
142
|
+
- **Alertas multi-canal** (Slack, Discord, Email)
|
|
143
|
+
- **CLI completo** para debug e automação
|
|
144
|
+
- **Fallback automático** entre fontes
|
|
145
145
|
|
|
146
146
|
## Como Funciona
|
|
147
147
|
|
|
@@ -157,7 +157,7 @@ Consultas a períodos antigos são instantâneas (cache). Apenas dados recentes
|
|
|
157
157
|
|
|
158
158
|
## Documentação
|
|
159
159
|
|
|
160
|
-
|
|
160
|
+
[Documentação completa](https://bruno-portfolio.github.io/agrobr/)
|
|
161
161
|
|
|
162
162
|
- [Guia Rápido](https://bruno-portfolio.github.io/agrobr/quickstart/)
|
|
163
163
|
- [API CEPEA](https://bruno-portfolio.github.io/agrobr/api/cepea/)
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
__version__ = "0.
|
|
5
|
+
__version__ = "0.2.0"
|
|
6
6
|
__author__ = "Bruno"
|
|
7
7
|
|
|
8
8
|
from agrobr import cepea, conab, ibge
|
|
9
|
+
from agrobr.models import MetaInfo
|
|
9
10
|
|
|
10
|
-
__all__ = ["cepea", "conab", "ibge", "__version__"]
|
|
11
|
+
__all__ = ["cepea", "conab", "ibge", "MetaInfo", "__version__"]
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
"""Benchmark suite para testes de performance do agrobr."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import statistics
|
|
6
|
+
import time
|
|
7
|
+
from collections.abc import Callable, Coroutine
|
|
8
|
+
from dataclasses import dataclass, field
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
import structlog
|
|
13
|
+
|
|
14
|
+
logger = structlog.get_logger()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class BenchmarkResult:
|
|
19
|
+
"""Resultado de um benchmark."""
|
|
20
|
+
|
|
21
|
+
name: str
|
|
22
|
+
iterations: int
|
|
23
|
+
total_time_ms: float
|
|
24
|
+
mean_time_ms: float
|
|
25
|
+
median_time_ms: float
|
|
26
|
+
min_time_ms: float
|
|
27
|
+
max_time_ms: float
|
|
28
|
+
std_dev_ms: float
|
|
29
|
+
times_ms: list[float] = field(default_factory=list)
|
|
30
|
+
timestamp: datetime = field(default_factory=datetime.now)
|
|
31
|
+
metadata: dict[str, Any] = field(default_factory=dict)
|
|
32
|
+
|
|
33
|
+
def to_dict(self) -> dict[str, Any]:
|
|
34
|
+
"""Converte para dicionario."""
|
|
35
|
+
return {
|
|
36
|
+
"name": self.name,
|
|
37
|
+
"iterations": self.iterations,
|
|
38
|
+
"total_time_ms": round(self.total_time_ms, 2),
|
|
39
|
+
"mean_time_ms": round(self.mean_time_ms, 2),
|
|
40
|
+
"median_time_ms": round(self.median_time_ms, 2),
|
|
41
|
+
"min_time_ms": round(self.min_time_ms, 2),
|
|
42
|
+
"max_time_ms": round(self.max_time_ms, 2),
|
|
43
|
+
"std_dev_ms": round(self.std_dev_ms, 2),
|
|
44
|
+
"timestamp": self.timestamp.isoformat(),
|
|
45
|
+
"metadata": self.metadata,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
def summary(self) -> str:
|
|
49
|
+
"""Retorna resumo formatado."""
|
|
50
|
+
return (
|
|
51
|
+
f"{self.name}: "
|
|
52
|
+
f"mean={self.mean_time_ms:.2f}ms, "
|
|
53
|
+
f"median={self.median_time_ms:.2f}ms, "
|
|
54
|
+
f"min={self.min_time_ms:.2f}ms, "
|
|
55
|
+
f"max={self.max_time_ms:.2f}ms "
|
|
56
|
+
f"({self.iterations} iterations)"
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@dataclass
|
|
61
|
+
class BenchmarkSuite:
|
|
62
|
+
"""Suite de benchmarks."""
|
|
63
|
+
|
|
64
|
+
name: str
|
|
65
|
+
results: list[BenchmarkResult] = field(default_factory=list)
|
|
66
|
+
timestamp: datetime = field(default_factory=datetime.now)
|
|
67
|
+
|
|
68
|
+
def add_result(self, result: BenchmarkResult) -> None:
|
|
69
|
+
"""Adiciona resultado."""
|
|
70
|
+
self.results.append(result)
|
|
71
|
+
|
|
72
|
+
def to_dict(self) -> dict[str, Any]:
|
|
73
|
+
"""Converte para dicionario."""
|
|
74
|
+
return {
|
|
75
|
+
"name": self.name,
|
|
76
|
+
"timestamp": self.timestamp.isoformat(),
|
|
77
|
+
"results": [r.to_dict() for r in self.results],
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
def summary(self) -> str:
|
|
81
|
+
"""Retorna resumo formatado."""
|
|
82
|
+
lines = [f"Benchmark Suite: {self.name}", "=" * 50]
|
|
83
|
+
for result in self.results:
|
|
84
|
+
lines.append(result.summary())
|
|
85
|
+
return "\n".join(lines)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
async def benchmark_async(
|
|
89
|
+
name: str,
|
|
90
|
+
func: Callable[..., Coroutine[Any, Any, Any]],
|
|
91
|
+
iterations: int = 10,
|
|
92
|
+
warmup: int = 1,
|
|
93
|
+
**kwargs: Any,
|
|
94
|
+
) -> BenchmarkResult:
|
|
95
|
+
"""
|
|
96
|
+
Executa benchmark de funcao async.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
name: Nome do benchmark
|
|
100
|
+
func: Funcao async a testar
|
|
101
|
+
iterations: Numero de iteracoes
|
|
102
|
+
warmup: Iteracoes de aquecimento
|
|
103
|
+
**kwargs: Argumentos para a funcao
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
BenchmarkResult com estatisticas
|
|
107
|
+
"""
|
|
108
|
+
for _ in range(warmup):
|
|
109
|
+
await func(**kwargs)
|
|
110
|
+
|
|
111
|
+
times: list[float] = []
|
|
112
|
+
for _ in range(iterations):
|
|
113
|
+
start = time.perf_counter()
|
|
114
|
+
await func(**kwargs)
|
|
115
|
+
elapsed = (time.perf_counter() - start) * 1000
|
|
116
|
+
times.append(elapsed)
|
|
117
|
+
|
|
118
|
+
return BenchmarkResult(
|
|
119
|
+
name=name,
|
|
120
|
+
iterations=iterations,
|
|
121
|
+
total_time_ms=sum(times),
|
|
122
|
+
mean_time_ms=statistics.mean(times),
|
|
123
|
+
median_time_ms=statistics.median(times),
|
|
124
|
+
min_time_ms=min(times),
|
|
125
|
+
max_time_ms=max(times),
|
|
126
|
+
std_dev_ms=statistics.stdev(times) if len(times) > 1 else 0,
|
|
127
|
+
times_ms=times,
|
|
128
|
+
metadata={"warmup": warmup, "kwargs": str(kwargs)},
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def benchmark_sync(
|
|
133
|
+
name: str,
|
|
134
|
+
func: Callable[..., Any],
|
|
135
|
+
iterations: int = 10,
|
|
136
|
+
warmup: int = 1,
|
|
137
|
+
**kwargs: Any,
|
|
138
|
+
) -> BenchmarkResult:
|
|
139
|
+
"""
|
|
140
|
+
Executa benchmark de funcao sincrona.
|
|
141
|
+
|
|
142
|
+
Args:
|
|
143
|
+
name: Nome do benchmark
|
|
144
|
+
func: Funcao a testar
|
|
145
|
+
iterations: Numero de iteracoes
|
|
146
|
+
warmup: Iteracoes de aquecimento
|
|
147
|
+
**kwargs: Argumentos para a funcao
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
BenchmarkResult com estatisticas
|
|
151
|
+
"""
|
|
152
|
+
for _ in range(warmup):
|
|
153
|
+
func(**kwargs)
|
|
154
|
+
|
|
155
|
+
times: list[float] = []
|
|
156
|
+
for _ in range(iterations):
|
|
157
|
+
start = time.perf_counter()
|
|
158
|
+
func(**kwargs)
|
|
159
|
+
elapsed = (time.perf_counter() - start) * 1000
|
|
160
|
+
times.append(elapsed)
|
|
161
|
+
|
|
162
|
+
return BenchmarkResult(
|
|
163
|
+
name=name,
|
|
164
|
+
iterations=iterations,
|
|
165
|
+
total_time_ms=sum(times),
|
|
166
|
+
mean_time_ms=statistics.mean(times),
|
|
167
|
+
median_time_ms=statistics.median(times),
|
|
168
|
+
min_time_ms=min(times),
|
|
169
|
+
max_time_ms=max(times),
|
|
170
|
+
std_dev_ms=statistics.stdev(times) if len(times) > 1 else 0,
|
|
171
|
+
times_ms=times,
|
|
172
|
+
metadata={"warmup": warmup, "kwargs": str(kwargs)},
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
async def run_api_benchmarks(iterations: int = 5) -> BenchmarkSuite:
|
|
177
|
+
"""
|
|
178
|
+
Executa benchmarks das APIs principais.
|
|
179
|
+
|
|
180
|
+
Args:
|
|
181
|
+
iterations: Numero de iteracoes por benchmark
|
|
182
|
+
|
|
183
|
+
Returns:
|
|
184
|
+
BenchmarkSuite com resultados
|
|
185
|
+
"""
|
|
186
|
+
from agrobr import cepea, conab, ibge
|
|
187
|
+
|
|
188
|
+
suite = BenchmarkSuite(name="agrobr_api_benchmarks")
|
|
189
|
+
|
|
190
|
+
try:
|
|
191
|
+
result = await benchmark_async(
|
|
192
|
+
"cepea.indicador(soja, offline=True)",
|
|
193
|
+
cepea.indicador,
|
|
194
|
+
iterations=iterations,
|
|
195
|
+
produto="soja",
|
|
196
|
+
offline=True,
|
|
197
|
+
)
|
|
198
|
+
suite.add_result(result)
|
|
199
|
+
except Exception as e:
|
|
200
|
+
logger.warning("benchmark_failed", name="cepea.indicador", error=str(e))
|
|
201
|
+
|
|
202
|
+
try:
|
|
203
|
+
result = await benchmark_async(
|
|
204
|
+
"cepea.produtos()",
|
|
205
|
+
cepea.produtos,
|
|
206
|
+
iterations=iterations,
|
|
207
|
+
)
|
|
208
|
+
suite.add_result(result)
|
|
209
|
+
except Exception as e:
|
|
210
|
+
logger.warning("benchmark_failed", name="cepea.produtos", error=str(e))
|
|
211
|
+
|
|
212
|
+
try:
|
|
213
|
+
result = await benchmark_async(
|
|
214
|
+
"conab.produtos()",
|
|
215
|
+
conab.produtos,
|
|
216
|
+
iterations=iterations,
|
|
217
|
+
)
|
|
218
|
+
suite.add_result(result)
|
|
219
|
+
except Exception as e:
|
|
220
|
+
logger.warning("benchmark_failed", name="conab.produtos", error=str(e))
|
|
221
|
+
|
|
222
|
+
try:
|
|
223
|
+
result = await benchmark_async(
|
|
224
|
+
"ibge.produtos_pam()",
|
|
225
|
+
ibge.produtos_pam,
|
|
226
|
+
iterations=iterations,
|
|
227
|
+
)
|
|
228
|
+
suite.add_result(result)
|
|
229
|
+
except Exception as e:
|
|
230
|
+
logger.warning("benchmark_failed", name="ibge.produtos_pam", error=str(e))
|
|
231
|
+
|
|
232
|
+
return suite
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def run_contract_benchmarks(iterations: int = 100) -> BenchmarkSuite:
|
|
236
|
+
"""
|
|
237
|
+
Executa benchmarks de validacao de contratos.
|
|
238
|
+
|
|
239
|
+
Args:
|
|
240
|
+
iterations: Numero de iteracoes por benchmark
|
|
241
|
+
|
|
242
|
+
Returns:
|
|
243
|
+
BenchmarkSuite com resultados
|
|
244
|
+
"""
|
|
245
|
+
import pandas as pd
|
|
246
|
+
|
|
247
|
+
from agrobr.contracts.cepea import CEPEA_INDICADOR_V1
|
|
248
|
+
|
|
249
|
+
suite = BenchmarkSuite(name="contract_validation_benchmarks")
|
|
250
|
+
|
|
251
|
+
df_small = pd.DataFrame(
|
|
252
|
+
{
|
|
253
|
+
"data": pd.date_range("2024-01-01", periods=10),
|
|
254
|
+
"produto": ["soja"] * 10,
|
|
255
|
+
"praca": ["paranagua"] * 10,
|
|
256
|
+
"valor": [150.0] * 10,
|
|
257
|
+
"unidade": ["BRL/sc60kg"] * 10,
|
|
258
|
+
"fonte": ["cepea"] * 10,
|
|
259
|
+
"metodologia": [None] * 10,
|
|
260
|
+
"anomalies": [None] * 10,
|
|
261
|
+
}
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
result = benchmark_sync(
|
|
265
|
+
"contract.validate(10 rows)",
|
|
266
|
+
CEPEA_INDICADOR_V1.validate,
|
|
267
|
+
iterations=iterations,
|
|
268
|
+
df=df_small,
|
|
269
|
+
)
|
|
270
|
+
suite.add_result(result)
|
|
271
|
+
|
|
272
|
+
df_large = pd.DataFrame(
|
|
273
|
+
{
|
|
274
|
+
"data": pd.date_range("2020-01-01", periods=1000),
|
|
275
|
+
"produto": ["soja"] * 1000,
|
|
276
|
+
"praca": ["paranagua"] * 1000,
|
|
277
|
+
"valor": [150.0] * 1000,
|
|
278
|
+
"unidade": ["BRL/sc60kg"] * 1000,
|
|
279
|
+
"fonte": ["cepea"] * 1000,
|
|
280
|
+
"metodologia": [None] * 1000,
|
|
281
|
+
"anomalies": [None] * 1000,
|
|
282
|
+
}
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
result = benchmark_sync(
|
|
286
|
+
"contract.validate(1000 rows)",
|
|
287
|
+
CEPEA_INDICADOR_V1.validate,
|
|
288
|
+
iterations=iterations,
|
|
289
|
+
df=df_large,
|
|
290
|
+
)
|
|
291
|
+
suite.add_result(result)
|
|
292
|
+
|
|
293
|
+
return suite
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
def run_semantic_benchmarks(iterations: int = 50) -> BenchmarkSuite:
|
|
297
|
+
"""
|
|
298
|
+
Executa benchmarks de validacao semantica.
|
|
299
|
+
|
|
300
|
+
Args:
|
|
301
|
+
iterations: Numero de iteracoes por benchmark
|
|
302
|
+
|
|
303
|
+
Returns:
|
|
304
|
+
BenchmarkSuite com resultados
|
|
305
|
+
"""
|
|
306
|
+
import pandas as pd
|
|
307
|
+
|
|
308
|
+
from agrobr.validators.semantic import validate_semantic
|
|
309
|
+
|
|
310
|
+
suite = BenchmarkSuite(name="semantic_validation_benchmarks")
|
|
311
|
+
|
|
312
|
+
df = pd.DataFrame(
|
|
313
|
+
{
|
|
314
|
+
"data": pd.date_range("2024-01-01", periods=100),
|
|
315
|
+
"valor": [150.0 + i * 0.5 for i in range(100)],
|
|
316
|
+
"produto": ["soja"] * 100,
|
|
317
|
+
"produtividade": [3500.0] * 100,
|
|
318
|
+
"area_plantada": [1000.0] * 100,
|
|
319
|
+
"area_colhida": [950.0] * 100,
|
|
320
|
+
"safra": ["2024/25"] * 100,
|
|
321
|
+
}
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
result = benchmark_sync(
|
|
325
|
+
"validate_semantic(100 rows)",
|
|
326
|
+
validate_semantic,
|
|
327
|
+
iterations=iterations,
|
|
328
|
+
df=df,
|
|
329
|
+
)
|
|
330
|
+
suite.add_result(result)
|
|
331
|
+
|
|
332
|
+
return suite
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
__all__ = [
|
|
336
|
+
"BenchmarkResult",
|
|
337
|
+
"BenchmarkSuite",
|
|
338
|
+
"benchmark_async",
|
|
339
|
+
"benchmark_sync",
|
|
340
|
+
"run_api_benchmarks",
|
|
341
|
+
"run_contract_benchmarks",
|
|
342
|
+
"run_semantic_benchmarks",
|
|
343
|
+
]
|