agrobr 0.1.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.
Files changed (104) hide show
  1. agrobr-0.1.0/.github/workflows/health_check.yml +38 -0
  2. agrobr-0.1.0/.github/workflows/publish.yml +127 -0
  3. agrobr-0.1.0/.github/workflows/structure_monitor.yml +41 -0
  4. agrobr-0.1.0/.github/workflows/tests.yml +46 -0
  5. agrobr-0.1.0/.gitignore +2 -0
  6. agrobr-0.1.0/.pre-commit-config.yaml +29 -0
  7. agrobr-0.1.0/.structures/baseline.json +35 -0
  8. agrobr-0.1.0/CHANGELOG.md +60 -0
  9. agrobr-0.1.0/CODE_OF_CONDUCT.md +41 -0
  10. agrobr-0.1.0/CONTRIBUTING.md +167 -0
  11. agrobr-0.1.0/LICENSE +21 -0
  12. agrobr-0.1.0/PKG-INFO +243 -0
  13. agrobr-0.1.0/README.md +174 -0
  14. agrobr-0.1.0/agrobr/__init__.py +10 -0
  15. agrobr-0.1.0/agrobr/alerts/__init__.py +7 -0
  16. agrobr-0.1.0/agrobr/alerts/notifier.py +167 -0
  17. agrobr-0.1.0/agrobr/cache/__init__.py +31 -0
  18. agrobr-0.1.0/agrobr/cache/duckdb_store.py +433 -0
  19. agrobr-0.1.0/agrobr/cache/history.py +317 -0
  20. agrobr-0.1.0/agrobr/cache/migrations.py +82 -0
  21. agrobr-0.1.0/agrobr/cache/policies.py +240 -0
  22. agrobr-0.1.0/agrobr/cepea/__init__.py +7 -0
  23. agrobr-0.1.0/agrobr/cepea/api.py +360 -0
  24. agrobr-0.1.0/agrobr/cepea/client.py +273 -0
  25. agrobr-0.1.0/agrobr/cepea/parsers/__init__.py +37 -0
  26. agrobr-0.1.0/agrobr/cepea/parsers/base.py +35 -0
  27. agrobr-0.1.0/agrobr/cepea/parsers/consensus.py +300 -0
  28. agrobr-0.1.0/agrobr/cepea/parsers/detector.py +108 -0
  29. agrobr-0.1.0/agrobr/cepea/parsers/fingerprint.py +226 -0
  30. agrobr-0.1.0/agrobr/cepea/parsers/v1.py +305 -0
  31. agrobr-0.1.0/agrobr/cli.py +323 -0
  32. agrobr-0.1.0/agrobr/conab/__init__.py +21 -0
  33. agrobr-0.1.0/agrobr/conab/api.py +239 -0
  34. agrobr-0.1.0/agrobr/conab/client.py +219 -0
  35. agrobr-0.1.0/agrobr/conab/parsers/__init__.py +7 -0
  36. agrobr-0.1.0/agrobr/conab/parsers/v1.py +383 -0
  37. agrobr-0.1.0/agrobr/constants.py +205 -0
  38. agrobr-0.1.0/agrobr/exceptions.py +104 -0
  39. agrobr-0.1.0/agrobr/health/__init__.py +23 -0
  40. agrobr-0.1.0/agrobr/health/checker.py +202 -0
  41. agrobr-0.1.0/agrobr/health/reporter.py +314 -0
  42. agrobr-0.1.0/agrobr/http/__init__.py +9 -0
  43. agrobr-0.1.0/agrobr/http/browser.py +214 -0
  44. agrobr-0.1.0/agrobr/http/rate_limiter.py +69 -0
  45. agrobr-0.1.0/agrobr/http/retry.py +93 -0
  46. agrobr-0.1.0/agrobr/http/user_agents.py +67 -0
  47. agrobr-0.1.0/agrobr/ibge/__init__.py +19 -0
  48. agrobr-0.1.0/agrobr/ibge/api.py +273 -0
  49. agrobr-0.1.0/agrobr/ibge/client.py +256 -0
  50. agrobr-0.1.0/agrobr/models.py +85 -0
  51. agrobr-0.1.0/agrobr/normalize/__init__.py +64 -0
  52. agrobr-0.1.0/agrobr/normalize/dates.py +303 -0
  53. agrobr-0.1.0/agrobr/normalize/encoding.py +102 -0
  54. agrobr-0.1.0/agrobr/normalize/regions.py +308 -0
  55. agrobr-0.1.0/agrobr/normalize/units.py +278 -0
  56. agrobr-0.1.0/agrobr/noticias_agricolas/__init__.py +6 -0
  57. agrobr-0.1.0/agrobr/noticias_agricolas/client.py +222 -0
  58. agrobr-0.1.0/agrobr/noticias_agricolas/parser.py +187 -0
  59. agrobr-0.1.0/agrobr/sync.py +147 -0
  60. agrobr-0.1.0/agrobr/telemetry/__init__.py +17 -0
  61. agrobr-0.1.0/agrobr/telemetry/collector.py +153 -0
  62. agrobr-0.1.0/agrobr/utils/__init__.py +5 -0
  63. agrobr-0.1.0/agrobr/utils/logging.py +59 -0
  64. agrobr-0.1.0/agrobr/validators/__init__.py +35 -0
  65. agrobr-0.1.0/agrobr/validators/sanity.py +286 -0
  66. agrobr-0.1.0/agrobr/validators/structural.py +313 -0
  67. agrobr-0.1.0/docs/advanced/resilience.md +251 -0
  68. agrobr-0.1.0/docs/advanced/troubleshooting.md +269 -0
  69. agrobr-0.1.0/docs/api/cepea.md +192 -0
  70. agrobr-0.1.0/docs/api/conab.md +204 -0
  71. agrobr-0.1.0/docs/api/ibge.md +180 -0
  72. agrobr-0.1.0/docs/index.md +84 -0
  73. agrobr-0.1.0/docs/quickstart.md +267 -0
  74. agrobr-0.1.0/examples/analise_soja.py +122 -0
  75. agrobr-0.1.0/examples/pipeline_async.py +129 -0
  76. agrobr-0.1.0/mkdocs.yml +84 -0
  77. agrobr-0.1.0/pyproject.toml +165 -0
  78. agrobr-0.1.0/scripts/alert_structure_change.py +60 -0
  79. agrobr-0.1.0/scripts/compare_structures.py +133 -0
  80. agrobr-0.1.0/scripts/create_workflows.py +153 -0
  81. agrobr-0.1.0/scripts/fetch_structures.py +54 -0
  82. agrobr-0.1.0/scripts/update_golden.py +110 -0
  83. agrobr-0.1.0/tests/__init__.py +1 -0
  84. agrobr-0.1.0/tests/conftest.py +91 -0
  85. agrobr-0.1.0/tests/golden_data/cepea/soja_sample/expected.json +14 -0
  86. agrobr-0.1.0/tests/golden_data/cepea/soja_sample/metadata.json +9 -0
  87. agrobr-0.1.0/tests/golden_data/cepea/soja_sample/response.html +137 -0
  88. agrobr-0.1.0/tests/golden_data/conab/safra_sample/expected.json +31 -0
  89. agrobr-0.1.0/tests/golden_data/conab/safra_sample/metadata.json +11 -0
  90. agrobr-0.1.0/tests/golden_data/conab/safra_sample/response.xlsx +0 -0
  91. agrobr-0.1.0/tests/test_cepea/__init__.py +1 -0
  92. agrobr-0.1.0/tests/test_cepea/test_api.py +33 -0
  93. agrobr-0.1.0/tests/test_cepea/test_fingerprint.py +64 -0
  94. agrobr-0.1.0/tests/test_cepea/test_parser.py +80 -0
  95. agrobr-0.1.0/tests/test_conab/__init__.py +1 -0
  96. agrobr-0.1.0/tests/test_conab/test_parser.py +178 -0
  97. agrobr-0.1.0/tests/test_golden.py +225 -0
  98. agrobr-0.1.0/tests/test_ibge/__init__.py +1 -0
  99. agrobr-0.1.0/tests/test_ibge/test_api.py +338 -0
  100. agrobr-0.1.0/tests/test_ibge/test_client.py +199 -0
  101. agrobr-0.1.0/tests/test_noticias_agricolas/__init__.py +1 -0
  102. agrobr-0.1.0/tests/test_noticias_agricolas/test_parser.py +155 -0
  103. agrobr-0.1.0/tests/test_validators/__init__.py +1 -0
  104. agrobr-0.1.0/tests/test_validators/test_sanity.py +117 -0
@@ -0,0 +1,38 @@
1
+ name: Daily Health Check
2
+
3
+ on:
4
+ schedule:
5
+ - cron: '0 12 * * *'
6
+ - cron: '0 0 * * *'
7
+ workflow_dispatch:
8
+
9
+ jobs:
10
+ health:
11
+ runs-on: ubuntu-latest
12
+ timeout-minutes: 15
13
+
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+
17
+ - name: Setup Python
18
+ uses: actions/setup-python@v5
19
+ with:
20
+ python-version: '3.11'
21
+ cache: 'pip'
22
+
23
+ - name: Install dependencies
24
+ run: |
25
+ pip install -e ".[dev]"
26
+
27
+ - name: Run health checks
28
+ id: health
29
+ run: |
30
+ python scripts/fetch_structures.py --output health_report.json
31
+ echo "report_path=health_report.json" >> $GITHUB_OUTPUT
32
+
33
+ - name: Upload report
34
+ uses: actions/upload-artifact@v4
35
+ with:
36
+ name: health-report-${{ github.run_number }}
37
+ path: health_report.json
38
+ retention-days: 30
@@ -0,0 +1,127 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+ workflow_dispatch:
7
+ inputs:
8
+ test_pypi:
9
+ description: 'Publish to Test PyPI instead'
10
+ required: false
11
+ default: 'false'
12
+ type: boolean
13
+
14
+ jobs:
15
+ build:
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - name: Setup Python
21
+ uses: actions/setup-python@v5
22
+ with:
23
+ python-version: '3.11'
24
+
25
+ - name: Install build tools
26
+ run: |
27
+ python -m pip install --upgrade pip
28
+ pip install build twine
29
+
30
+ - name: Build package
31
+ run: python -m build
32
+
33
+ - name: Check package
34
+ run: twine check dist/*
35
+
36
+ - name: Upload artifacts
37
+ uses: actions/upload-artifact@v4
38
+ with:
39
+ name: dist
40
+ path: dist/
41
+
42
+ test:
43
+ needs: build
44
+ runs-on: ubuntu-latest
45
+ steps:
46
+ - uses: actions/checkout@v4
47
+
48
+ - name: Setup Python
49
+ uses: actions/setup-python@v5
50
+ with:
51
+ python-version: '3.11'
52
+
53
+ - name: Download artifacts
54
+ uses: actions/download-artifact@v4
55
+ with:
56
+ name: dist
57
+ path: dist/
58
+
59
+ - name: Install package from wheel
60
+ run: |
61
+ pip install dist/*.whl
62
+
63
+ - name: Test import
64
+ run: |
65
+ python -c "import agrobr; print(f'agrobr version: {agrobr.__version__}')"
66
+ python -c "from agrobr import cepea, conab, ibge; print('All modules imported successfully')"
67
+
68
+ - name: Test CLI
69
+ run: |
70
+ agrobr --help
71
+ agrobr cepea --help
72
+ agrobr conab --help
73
+ agrobr ibge --help
74
+
75
+ publish-test-pypi:
76
+ needs: [build, test]
77
+ runs-on: ubuntu-latest
78
+ if: github.event.inputs.test_pypi == 'true'
79
+ environment: test-pypi
80
+ permissions:
81
+ id-token: write
82
+ steps:
83
+ - name: Download artifacts
84
+ uses: actions/download-artifact@v4
85
+ with:
86
+ name: dist
87
+ path: dist/
88
+
89
+ - name: Publish to Test PyPI
90
+ uses: pypa/gh-action-pypi-publish@release/v1
91
+ with:
92
+ repository-url: https://test.pypi.org/legacy/
93
+
94
+ publish-pypi:
95
+ needs: [build, test]
96
+ runs-on: ubuntu-latest
97
+ if: github.event_name == 'release' && github.event.inputs.test_pypi != 'true'
98
+ environment: pypi
99
+ permissions:
100
+ id-token: write
101
+ steps:
102
+ - name: Download artifacts
103
+ uses: actions/download-artifact@v4
104
+ with:
105
+ name: dist
106
+ path: dist/
107
+
108
+ - name: Publish to PyPI
109
+ uses: pypa/gh-action-pypi-publish@release/v1
110
+
111
+ github-release:
112
+ needs: publish-pypi
113
+ runs-on: ubuntu-latest
114
+ if: github.event_name == 'release'
115
+ permissions:
116
+ contents: write
117
+ steps:
118
+ - name: Download artifacts
119
+ uses: actions/download-artifact@v4
120
+ with:
121
+ name: dist
122
+ path: dist/
123
+
124
+ - name: Upload release assets
125
+ uses: softprops/action-gh-release@v1
126
+ with:
127
+ files: dist/*
@@ -0,0 +1,41 @@
1
+ name: Structure Monitor
2
+
3
+ on:
4
+ schedule:
5
+ - cron: '0 */6 * * *'
6
+ workflow_dispatch:
7
+
8
+ jobs:
9
+ monitor:
10
+ runs-on: ubuntu-latest
11
+ timeout-minutes: 10
12
+
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+
16
+ - name: Setup Python
17
+ uses: actions/setup-python@v5
18
+ with:
19
+ python-version: '3.11'
20
+ cache: 'pip'
21
+
22
+ - name: Install dependencies
23
+ run: pip install -e ".[dev]"
24
+
25
+ - name: Fetch current structures
26
+ run: |
27
+ python scripts/fetch_structures.py --output current_structures.json
28
+
29
+ - name: Compare with baseline
30
+ id: compare
31
+ run: |
32
+ python scripts/compare_structures.py \
33
+ --baseline .structures/baseline.json \
34
+ --current current_structures.json \
35
+ --threshold 0.85 \
36
+ --output diff_report.json || echo "drift_detected=true" >> $GITHUB_OUTPUT
37
+
38
+ - name: Alert on drift
39
+ if: steps.compare.outputs.drift_detected == 'true'
40
+ run: |
41
+ python scripts/alert_structure_change.py diff_report.json
@@ -0,0 +1,46 @@
1
+ name: Tests
2
+
3
+ on:
4
+ push:
5
+ branches: [main, develop]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python-version: ["3.11", "3.12"]
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Setup Python ${{ matrix.python-version }}
20
+ uses: actions/setup-python@v5
21
+ with:
22
+ python-version: ${{ matrix.python-version }}
23
+ cache: "pip"
24
+
25
+ - name: Install dependencies
26
+ run: |
27
+ pip install -e ".[dev]"
28
+
29
+ - name: Run linting
30
+ run: |
31
+ ruff check agrobr/ tests/
32
+ ruff format --check agrobr/ tests/
33
+
34
+ - name: Run type checking
35
+ run: |
36
+ mypy agrobr/
37
+
38
+ - name: Run tests
39
+ run: |
40
+ pytest tests/ -v --cov=agrobr --cov-report=xml --cov-report=term-missing
41
+
42
+ - name: Upload coverage
43
+ uses: codecov/codecov-action@v4
44
+ with:
45
+ files: ./coverage.xml
46
+ fail_ci_if_error: false
@@ -0,0 +1,2 @@
1
+ nul
2
+ agrobr_v3.txt
@@ -0,0 +1,29 @@
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v4.5.0
4
+ hooks:
5
+ - id: trailing-whitespace
6
+ - id: end-of-file-fixer
7
+ - id: check-yaml
8
+ - id: check-added-large-files
9
+ - id: check-merge-conflict
10
+ - id: debug-statements
11
+
12
+ - repo: https://github.com/astral-sh/ruff-pre-commit
13
+ rev: v0.1.6
14
+ hooks:
15
+ - id: ruff
16
+ args: [--fix, --exit-non-zero-on-fix]
17
+ - id: ruff-format
18
+
19
+ - repo: https://github.com/pre-commit/mirrors-mypy
20
+ rev: v1.7.1
21
+ hooks:
22
+ - id: mypy
23
+ additional_dependencies:
24
+ - pydantic>=2.5.0
25
+ - pydantic-settings>=2.1.0
26
+ - httpx>=0.25.0
27
+ - pandas-stubs>=2.0.0
28
+ - types-beautifulsoup4>=4.12.0
29
+ args: [--ignore-missing-imports]
@@ -0,0 +1,35 @@
1
+ {
2
+ "collected_at": "2026-02-04T01:02:57.512333Z",
3
+ "sources": {
4
+ "cepea": {
5
+ "source": "cepea",
6
+ "url": "soja",
7
+ "collected_at": "2026-02-04T01:02:57.512224",
8
+ "table_classes": [
9
+ [
10
+ "indicador"
11
+ ]
12
+ ],
13
+ "key_ids": [
14
+ "tblIndicador"
15
+ ],
16
+ "structure_hash": "d702ed66de78",
17
+ "table_headers": [
18
+ [
19
+ "Data",
20
+ "Valor (R$/sc 60kg)",
21
+ "Varia\u00e7\u00e3o (%)"
22
+ ]
23
+ ],
24
+ "element_counts": {
25
+ "tables": 1,
26
+ "forms": 0,
27
+ "divs_with_id": 1,
28
+ "inputs": 0,
29
+ "selects": 0,
30
+ "links": 0,
31
+ "scripts": 0
32
+ }
33
+ }
34
+ }
35
+ }
@@ -0,0 +1,60 @@
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
+ ### Added
11
+ - Suporte inicial para IBGE (PAM e LSPA)
12
+ - Golden data tests para CONAB
13
+
14
+ ## [0.1.0] - 2026-02-04
15
+
16
+ ### Added
17
+ - **CEPEA**: Indicadores de preços agrícolas (soja, milho, boi, café, algodão, trigo)
18
+ - Fallback automático para Notícias Agrícolas quando CEPEA bloqueado
19
+ - Acumulação progressiva de histórico no DuckDB
20
+ - **CONAB**: Dados de safras e balanço oferta/demanda
21
+ - Parser para planilhas XLSX do boletim de safras
22
+ - Suporte a todos os produtos principais (soja, milho, arroz, feijão, etc.)
23
+ - **IBGE**: Integração com API SIDRA
24
+ - PAM (Produção Agrícola Municipal) - dados anuais
25
+ - LSPA (Levantamento Sistemático) - estimativas mensais
26
+ - **Cache**: Sistema de cache com DuckDB
27
+ - Separação entre cache volátil e histórico permanente
28
+ - TTL configurável por fonte
29
+ - Acumulação progressiva de dados
30
+ - **HTTP**: Cliente robusto com resiliência
31
+ - Retry com exponential backoff
32
+ - Rate limiting por fonte
33
+ - User-agent rotativo
34
+ - Fallback para Playwright quando necessário
35
+ - **CLI**: Interface de linha de comando completa
36
+ - Comandos para CEPEA, CONAB e IBGE
37
+ - Exportação em CSV, JSON e Parquet
38
+ - **Validação**: Sistema de validação multinível
39
+ - Pydantic v2 para validação de tipos
40
+ - Validação estatística (sanity checks)
41
+ - Fingerprinting de layout para detecção de mudanças
42
+ - **Monitoramento**: Health checks e alertas
43
+ - Health check por fonte
44
+ - Alertas multi-canal (Slack, Discord, Email)
45
+ - Monitoramento de estrutura (6h)
46
+ - **Suporte Polars**: Todas as APIs suportam `as_polars=True`
47
+ - **Testes**: 96 testes passando (~80% cobertura)
48
+ - **CI/CD**: GitHub Actions configurados
49
+ - Testes automatizados
50
+ - Health check diário
51
+ - Monitoramento de estrutura
52
+
53
+ ### Technical Details
54
+ - Python 3.11+ required
55
+ - Async-first design com sync wrapper
56
+ - Type hints completos
57
+ - Logging estruturado com structlog
58
+
59
+ [Unreleased]: https://github.com/bruno-portfolio/agrobr/compare/v0.1.0...HEAD
60
+ [0.1.0]: https://github.com/bruno-portfolio/agrobr/releases/tag/v0.1.0
@@ -0,0 +1,41 @@
1
+ # Código de Conduta
2
+
3
+ ## Nosso Compromisso
4
+
5
+ No interesse de promover um ambiente aberto e acolhedor, nós, como contribuidores e mantenedores, nos comprometemos a fazer da participação em nosso projeto e em nossa comunidade uma experiência livre de assédio para todos, independentemente de idade, tamanho corporal, deficiência, etnia, características sexuais, identidade e expressão de gênero, nível de experiência, educação, status socioeconômico, nacionalidade, aparência pessoal, raça, religião ou identidade e orientação sexual.
6
+
7
+ ## Nossos Padrões
8
+
9
+ Exemplos de comportamento que contribuem para criar um ambiente positivo incluem:
10
+
11
+ * Usar linguagem acolhedora e inclusiva
12
+ * Respeitar pontos de vista e experiências diferentes
13
+ * Aceitar críticas construtivas com elegância
14
+ * Focar no que é melhor para a comunidade
15
+ * Mostrar empatia com outros membros da comunidade
16
+
17
+ Exemplos de comportamento inaceitável incluem:
18
+
19
+ * Uso de linguagem ou imagens sexualizadas e atenção ou avanços sexuais indesejados
20
+ * Comentários insultuosos/depreciativos e ataques pessoais ou políticos
21
+ * Assédio público ou privado
22
+ * Publicar informações privadas de outros sem permissão explícita
23
+ * Outras condutas que poderiam ser consideradas inadequadas em um ambiente profissional
24
+
25
+ ## Nossas Responsabilidades
26
+
27
+ Os mantenedores do projeto são responsáveis por esclarecer os padrões de comportamento aceitável e devem tomar ações corretivas apropriadas e justas em resposta a quaisquer instâncias de comportamento inaceitável.
28
+
29
+ Os mantenedores do projeto têm o direito e a responsabilidade de remover, editar ou rejeitar comentários, commits, código, edições de wiki, issues e outras contribuições que não estejam alinhadas a este Código de Conduta, ou banir temporariamente ou permanentemente qualquer contribuidor por outros comportamentos que considerem inadequados, ameaçadores, ofensivos ou prejudiciais.
30
+
31
+ ## Escopo
32
+
33
+ Este Código de Conduta se aplica tanto em espaços do projeto quanto em espaços públicos quando um indivíduo está representando o projeto ou sua comunidade. Exemplos de representação do projeto incluem usar um endereço de e-mail oficial do projeto, postar através de uma conta oficial de mídia social, ou atuar como representante designado em um evento online ou offline.
34
+
35
+ ## Aplicação
36
+
37
+ Instâncias de comportamento abusivo, de assédio ou de outra forma inaceitável podem ser reportadas entrando em contato com a equipe do projeto. Todas as reclamações serão revisadas e investigadas e resultarão em uma resposta que é considerada necessária e apropriada às circunstâncias. A equipe do projeto é obrigada a manter confidencialidade em relação ao relator de um incidente.
38
+
39
+ ## Atribuição
40
+
41
+ Este Código de Conduta é adaptado do [Contributor Covenant](https://www.contributor-covenant.org), versão 1.4, disponível em https://www.contributor-covenant.org/pt-br/version/1/4/code-of-conduct.html
@@ -0,0 +1,167 @@
1
+ # Contribuindo para o agrobr
2
+
3
+ Obrigado pelo interesse em contribuir com o agrobr! Este documento fornece diretrizes para contribuições.
4
+
5
+ ## Como Contribuir
6
+
7
+ ### Reportando Bugs
8
+
9
+ 1. Verifique se o bug já não foi reportado nas [Issues](https://github.com/bruno-portfolio/agrobr/issues)
10
+ 2. Se não encontrar, abra uma nova issue com:
11
+ - Título descritivo
12
+ - Passos para reproduzir
13
+ - Comportamento esperado vs atual
14
+ - Versão do Python e do agrobr
15
+ - Sistema operacional
16
+
17
+ ### Sugerindo Melhorias
18
+
19
+ 1. Abra uma issue descrevendo a melhoria
20
+ 2. Explique o caso de uso
21
+ 3. Discuta a implementação antes de começar
22
+
23
+ ### Pull Requests
24
+
25
+ 1. Fork o repositório
26
+ 2. Crie uma branch para sua feature: `git checkout -b feature/nova-feature`
27
+ 3. Faça commits com mensagens claras
28
+ 4. Escreva testes para novas funcionalidades
29
+ 5. Certifique-se que todos os testes passam
30
+ 6. Abra um Pull Request
31
+
32
+ ## Setup de Desenvolvimento
33
+
34
+ ```bash
35
+ # Clone o repositório
36
+ git clone https://github.com/bruno-portfolio/agrobr.git
37
+ cd agrobr
38
+
39
+ # Crie ambiente virtual
40
+ python -m venv .venv
41
+ source .venv/bin/activate # Linux/Mac
42
+ # ou
43
+ .venv\Scripts\activate # Windows
44
+
45
+ # Instale dependências de desenvolvimento
46
+ pip install -e ".[all]"
47
+
48
+ # Instale Playwright (necessário para alguns scrapers)
49
+ playwright install chromium
50
+
51
+ # Instale pre-commit hooks
52
+ pre-commit install
53
+ ```
54
+
55
+ ## Rodando Testes
56
+
57
+ ```bash
58
+ # Todos os testes
59
+ pytest
60
+
61
+ # Com cobertura
62
+ pytest --cov=agrobr --cov-report=html
63
+
64
+ # Apenas testes rápidos (sem network)
65
+ pytest -m "not slow"
66
+
67
+ # Testes de integração
68
+ pytest -m integration
69
+ ```
70
+
71
+ ## Padrões de Código
72
+
73
+ ### Style Guide
74
+
75
+ - Seguimos o [Google Python Style Guide](https://google.github.io/styleguide/pyguide.html)
76
+ - Formatação com `black` (line-length=100)
77
+ - Linting com `ruff`
78
+ - Type hints obrigatórios (verificados com `mypy --strict`)
79
+
80
+ ### Commits
81
+
82
+ - Use mensagens em português ou inglês
83
+ - Seja descritivo no que foi alterado
84
+ - Referencie issues quando aplicável: `Fix #123`
85
+
86
+ ### Docstrings
87
+
88
+ ```python
89
+ def funcao(param1: str, param2: int) -> bool:
90
+ """
91
+ Descrição curta da função.
92
+
93
+ Descrição mais detalhada se necessário.
94
+
95
+ Args:
96
+ param1: Descrição do primeiro parâmetro
97
+ param2: Descrição do segundo parâmetro
98
+
99
+ Returns:
100
+ Descrição do retorno
101
+
102
+ Raises:
103
+ ValueError: Quando param2 é negativo
104
+ """
105
+ pass
106
+ ```
107
+
108
+ ### Testes
109
+
110
+ - Um arquivo de teste por módulo: `tests/test_<modulo>/test_<arquivo>.py`
111
+ - Nomes descritivos: `test_<funcionalidade>_<cenario>`
112
+ - Use fixtures do pytest quando apropriado
113
+ - Mocke chamadas HTTP em testes unitários
114
+
115
+ ## Estrutura do Projeto
116
+
117
+ ```
118
+ agrobr/
119
+ ├── agrobr/
120
+ │ ├── cepea/ # Módulo CEPEA
121
+ │ ├── conab/ # Módulo CONAB
122
+ │ ├── ibge/ # Módulo IBGE
123
+ │ ├── cache/ # Sistema de cache DuckDB
124
+ │ ├── http/ # Cliente HTTP, retry, rate limiting
125
+ │ ├── normalize/ # Normalização de dados
126
+ │ ├── validators/ # Validação de dados
127
+ │ ├── health/ # Health checks
128
+ │ ├── alerts/ # Sistema de alertas
129
+ │ └── telemetry/ # Telemetria opt-in
130
+ ├── tests/ # Testes
131
+ ├── scripts/ # Scripts utilitários
132
+ ├── docs/ # Documentação
133
+ └── examples/ # Exemplos de uso
134
+ ```
135
+
136
+ ## Adicionando Nova Fonte de Dados
137
+
138
+ 1. Crie diretório: `agrobr/<fonte>/`
139
+ 2. Implemente:
140
+ - `client.py`: Cliente HTTP async
141
+ - `parsers/v1.py`: Parser com can_parse() e parse()
142
+ - `parsers/fingerprint.py`: Extração de fingerprint
143
+ - `api.py`: Funções públicas async
144
+ - `models.py` (se necessário): Modelos Pydantic específicos
145
+ 3. Adicione à CLI: `cli.py`
146
+ 4. Adicione constantes: `constants.py`
147
+ 5. Escreva testes
148
+ 6. Crie golden data
149
+ 7. Documente
150
+
151
+ ## Criando Novo Parser
152
+
153
+ Quando o layout de uma fonte muda:
154
+
155
+ 1. Crie `parsers/v{N+1}.py` baseado no anterior
156
+ 2. Atualize `valid_until` do parser antigo
157
+ 3. Atualize `expected_fingerprint` do novo
158
+ 4. Adicione golden data com HTML novo
159
+ 5. Verifique que testes antigos continuam passando
160
+ 6. **Nunca delete parsers antigos** (dados históricos podem precisar)
161
+
162
+ ## Dúvidas?
163
+
164
+ - Abra uma issue com a tag `question`
165
+ - Ou entre em contato via [email/discord/etc]
166
+
167
+ Obrigado por contribuir!
agrobr-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024-2026 Bruno
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.