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.
- agrobr-0.1.0/.github/workflows/health_check.yml +38 -0
- agrobr-0.1.0/.github/workflows/publish.yml +127 -0
- agrobr-0.1.0/.github/workflows/structure_monitor.yml +41 -0
- agrobr-0.1.0/.github/workflows/tests.yml +46 -0
- agrobr-0.1.0/.gitignore +2 -0
- agrobr-0.1.0/.pre-commit-config.yaml +29 -0
- agrobr-0.1.0/.structures/baseline.json +35 -0
- agrobr-0.1.0/CHANGELOG.md +60 -0
- agrobr-0.1.0/CODE_OF_CONDUCT.md +41 -0
- agrobr-0.1.0/CONTRIBUTING.md +167 -0
- agrobr-0.1.0/LICENSE +21 -0
- agrobr-0.1.0/PKG-INFO +243 -0
- agrobr-0.1.0/README.md +174 -0
- agrobr-0.1.0/agrobr/__init__.py +10 -0
- agrobr-0.1.0/agrobr/alerts/__init__.py +7 -0
- agrobr-0.1.0/agrobr/alerts/notifier.py +167 -0
- agrobr-0.1.0/agrobr/cache/__init__.py +31 -0
- agrobr-0.1.0/agrobr/cache/duckdb_store.py +433 -0
- agrobr-0.1.0/agrobr/cache/history.py +317 -0
- agrobr-0.1.0/agrobr/cache/migrations.py +82 -0
- agrobr-0.1.0/agrobr/cache/policies.py +240 -0
- agrobr-0.1.0/agrobr/cepea/__init__.py +7 -0
- agrobr-0.1.0/agrobr/cepea/api.py +360 -0
- agrobr-0.1.0/agrobr/cepea/client.py +273 -0
- agrobr-0.1.0/agrobr/cepea/parsers/__init__.py +37 -0
- agrobr-0.1.0/agrobr/cepea/parsers/base.py +35 -0
- agrobr-0.1.0/agrobr/cepea/parsers/consensus.py +300 -0
- agrobr-0.1.0/agrobr/cepea/parsers/detector.py +108 -0
- agrobr-0.1.0/agrobr/cepea/parsers/fingerprint.py +226 -0
- agrobr-0.1.0/agrobr/cepea/parsers/v1.py +305 -0
- agrobr-0.1.0/agrobr/cli.py +323 -0
- agrobr-0.1.0/agrobr/conab/__init__.py +21 -0
- agrobr-0.1.0/agrobr/conab/api.py +239 -0
- agrobr-0.1.0/agrobr/conab/client.py +219 -0
- agrobr-0.1.0/agrobr/conab/parsers/__init__.py +7 -0
- agrobr-0.1.0/agrobr/conab/parsers/v1.py +383 -0
- agrobr-0.1.0/agrobr/constants.py +205 -0
- agrobr-0.1.0/agrobr/exceptions.py +104 -0
- agrobr-0.1.0/agrobr/health/__init__.py +23 -0
- agrobr-0.1.0/agrobr/health/checker.py +202 -0
- agrobr-0.1.0/agrobr/health/reporter.py +314 -0
- agrobr-0.1.0/agrobr/http/__init__.py +9 -0
- agrobr-0.1.0/agrobr/http/browser.py +214 -0
- agrobr-0.1.0/agrobr/http/rate_limiter.py +69 -0
- agrobr-0.1.0/agrobr/http/retry.py +93 -0
- agrobr-0.1.0/agrobr/http/user_agents.py +67 -0
- agrobr-0.1.0/agrobr/ibge/__init__.py +19 -0
- agrobr-0.1.0/agrobr/ibge/api.py +273 -0
- agrobr-0.1.0/agrobr/ibge/client.py +256 -0
- agrobr-0.1.0/agrobr/models.py +85 -0
- agrobr-0.1.0/agrobr/normalize/__init__.py +64 -0
- agrobr-0.1.0/agrobr/normalize/dates.py +303 -0
- agrobr-0.1.0/agrobr/normalize/encoding.py +102 -0
- agrobr-0.1.0/agrobr/normalize/regions.py +308 -0
- agrobr-0.1.0/agrobr/normalize/units.py +278 -0
- agrobr-0.1.0/agrobr/noticias_agricolas/__init__.py +6 -0
- agrobr-0.1.0/agrobr/noticias_agricolas/client.py +222 -0
- agrobr-0.1.0/agrobr/noticias_agricolas/parser.py +187 -0
- agrobr-0.1.0/agrobr/sync.py +147 -0
- agrobr-0.1.0/agrobr/telemetry/__init__.py +17 -0
- agrobr-0.1.0/agrobr/telemetry/collector.py +153 -0
- agrobr-0.1.0/agrobr/utils/__init__.py +5 -0
- agrobr-0.1.0/agrobr/utils/logging.py +59 -0
- agrobr-0.1.0/agrobr/validators/__init__.py +35 -0
- agrobr-0.1.0/agrobr/validators/sanity.py +286 -0
- agrobr-0.1.0/agrobr/validators/structural.py +313 -0
- agrobr-0.1.0/docs/advanced/resilience.md +251 -0
- agrobr-0.1.0/docs/advanced/troubleshooting.md +269 -0
- agrobr-0.1.0/docs/api/cepea.md +192 -0
- agrobr-0.1.0/docs/api/conab.md +204 -0
- agrobr-0.1.0/docs/api/ibge.md +180 -0
- agrobr-0.1.0/docs/index.md +84 -0
- agrobr-0.1.0/docs/quickstart.md +267 -0
- agrobr-0.1.0/examples/analise_soja.py +122 -0
- agrobr-0.1.0/examples/pipeline_async.py +129 -0
- agrobr-0.1.0/mkdocs.yml +84 -0
- agrobr-0.1.0/pyproject.toml +165 -0
- agrobr-0.1.0/scripts/alert_structure_change.py +60 -0
- agrobr-0.1.0/scripts/compare_structures.py +133 -0
- agrobr-0.1.0/scripts/create_workflows.py +153 -0
- agrobr-0.1.0/scripts/fetch_structures.py +54 -0
- agrobr-0.1.0/scripts/update_golden.py +110 -0
- agrobr-0.1.0/tests/__init__.py +1 -0
- agrobr-0.1.0/tests/conftest.py +91 -0
- agrobr-0.1.0/tests/golden_data/cepea/soja_sample/expected.json +14 -0
- agrobr-0.1.0/tests/golden_data/cepea/soja_sample/metadata.json +9 -0
- agrobr-0.1.0/tests/golden_data/cepea/soja_sample/response.html +137 -0
- agrobr-0.1.0/tests/golden_data/conab/safra_sample/expected.json +31 -0
- agrobr-0.1.0/tests/golden_data/conab/safra_sample/metadata.json +11 -0
- agrobr-0.1.0/tests/golden_data/conab/safra_sample/response.xlsx +0 -0
- agrobr-0.1.0/tests/test_cepea/__init__.py +1 -0
- agrobr-0.1.0/tests/test_cepea/test_api.py +33 -0
- agrobr-0.1.0/tests/test_cepea/test_fingerprint.py +64 -0
- agrobr-0.1.0/tests/test_cepea/test_parser.py +80 -0
- agrobr-0.1.0/tests/test_conab/__init__.py +1 -0
- agrobr-0.1.0/tests/test_conab/test_parser.py +178 -0
- agrobr-0.1.0/tests/test_golden.py +225 -0
- agrobr-0.1.0/tests/test_ibge/__init__.py +1 -0
- agrobr-0.1.0/tests/test_ibge/test_api.py +338 -0
- agrobr-0.1.0/tests/test_ibge/test_client.py +199 -0
- agrobr-0.1.0/tests/test_noticias_agricolas/__init__.py +1 -0
- agrobr-0.1.0/tests/test_noticias_agricolas/test_parser.py +155 -0
- agrobr-0.1.0/tests/test_validators/__init__.py +1 -0
- 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
|
agrobr-0.1.0/.gitignore
ADDED
|
@@ -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.
|