aegro 0.2.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 (65) hide show
  1. aegro-0.2.0/.gitignore +37 -0
  2. aegro-0.2.0/LICENSE +21 -0
  3. aegro-0.2.0/PKG-INFO +240 -0
  4. aegro-0.2.0/README.md +207 -0
  5. aegro-0.2.0/aegro/__init__.py +4 -0
  6. aegro-0.2.0/aegro/_version.py +34 -0
  7. aegro-0.2.0/aegro/api_client.py +128 -0
  8. aegro-0.2.0/aegro/cli/__init__.py +64 -0
  9. aegro-0.2.0/aegro/cli/_auth.py +110 -0
  10. aegro-0.2.0/aegro/cli/_client.py +72 -0
  11. aegro-0.2.0/aegro/cli/_config.py +101 -0
  12. aegro-0.2.0/aegro/cli/_errors.py +44 -0
  13. aegro-0.2.0/aegro/cli/_output.py +82 -0
  14. aegro-0.2.0/aegro/cli/activities.py +276 -0
  15. aegro-0.2.0/aegro/cli/assets.py +432 -0
  16. aegro-0.2.0/aegro/cli/auth.py +92 -0
  17. aegro-0.2.0/aegro/cli/bank_accounts.py +147 -0
  18. aegro-0.2.0/aegro/cli/catalogs.py +113 -0
  19. aegro-0.2.0/aegro/cli/companies.py +136 -0
  20. aegro-0.2.0/aegro/cli/crop_glebes.py +73 -0
  21. aegro-0.2.0/aegro/cli/crops.py +219 -0
  22. aegro-0.2.0/aegro/cli/elements.py +311 -0
  23. aegro-0.2.0/aegro/cli/farms.py +81 -0
  24. aegro-0.2.0/aegro/cli/financial.py +278 -0
  25. aegro-0.2.0/aegro/cli/financial_categories.py +180 -0
  26. aegro-0.2.0/aegro/cli/fuel_supplies.py +184 -0
  27. aegro-0.2.0/aegro/cli/glebes.py +68 -0
  28. aegro-0.2.0/aegro/cli/harvest_logs.py +131 -0
  29. aegro-0.2.0/aegro/cli/maintenances.py +184 -0
  30. aegro-0.2.0/aegro/cli/purchase_orders.py +153 -0
  31. aegro-0.2.0/aegro/cli/stock.py +351 -0
  32. aegro-0.2.0/aegro/cli/tags.py +119 -0
  33. aegro-0.2.0/aegro/cli/weather.py +116 -0
  34. aegro-0.2.0/aegro/config.py +34 -0
  35. aegro-0.2.0/aegro/errors.py +72 -0
  36. aegro-0.2.0/aegro/validation.py +17 -0
  37. aegro-0.2.0/pyproject.toml +71 -0
  38. aegro-0.2.0/tests/__init__.py +0 -0
  39. aegro-0.2.0/tests/test_api_client.py +100 -0
  40. aegro-0.2.0/tests/test_cli/__init__.py +0 -0
  41. aegro-0.2.0/tests/test_cli/conftest.py +40 -0
  42. aegro-0.2.0/tests/test_cli/test_activities.py +280 -0
  43. aegro-0.2.0/tests/test_cli/test_assets.py +62 -0
  44. aegro-0.2.0/tests/test_cli/test_auth.py +82 -0
  45. aegro-0.2.0/tests/test_cli/test_bank_accounts.py +171 -0
  46. aegro-0.2.0/tests/test_cli/test_catalogs.py +101 -0
  47. aegro-0.2.0/tests/test_cli/test_companies.py +178 -0
  48. aegro-0.2.0/tests/test_cli/test_crop_glebes.py +31 -0
  49. aegro-0.2.0/tests/test_cli/test_crops.py +128 -0
  50. aegro-0.2.0/tests/test_cli/test_elements.py +283 -0
  51. aegro-0.2.0/tests/test_cli/test_farms.py +50 -0
  52. aegro-0.2.0/tests/test_cli/test_financial.py +289 -0
  53. aegro-0.2.0/tests/test_cli/test_financial_categories.py +216 -0
  54. aegro-0.2.0/tests/test_cli/test_fuel_supplies.py +205 -0
  55. aegro-0.2.0/tests/test_cli/test_glebes.py +38 -0
  56. aegro-0.2.0/tests/test_cli/test_harvest_logs.py +170 -0
  57. aegro-0.2.0/tests/test_cli/test_infrastructure.py +312 -0
  58. aegro-0.2.0/tests/test_cli/test_maintenances.py +203 -0
  59. aegro-0.2.0/tests/test_cli/test_purchase_orders.py +204 -0
  60. aegro-0.2.0/tests/test_cli/test_stock.py +432 -0
  61. aegro-0.2.0/tests/test_cli/test_tags.py +130 -0
  62. aegro-0.2.0/tests/test_cli/test_weather.py +173 -0
  63. aegro-0.2.0/tests/test_config.py +54 -0
  64. aegro-0.2.0/tests/test_errors.py +60 -0
  65. aegro-0.2.0/tests/test_validation.py +28 -0
aegro-0.2.0/.gitignore ADDED
@@ -0,0 +1,37 @@
1
+ # Environment & secrets
2
+ .env
3
+ .env.*
4
+ !.env.example
5
+ .farms.json
6
+
7
+ # Python
8
+ __pycache__/
9
+ *.py[cod]
10
+ *$py.class
11
+ *.egg-info/
12
+ dist/
13
+ build/
14
+ aegro/_version.py
15
+ *.egg
16
+
17
+ # Testing
18
+ .pytest_cache/
19
+ .coverage
20
+ htmlcov/
21
+
22
+ # IDE
23
+ .vscode/
24
+ .idea/
25
+ *.swp
26
+ *.swo
27
+
28
+ # OS
29
+ .DS_Store
30
+ Thumbs.db
31
+
32
+ # Virtual environments
33
+ .venv/
34
+ venv/
35
+
36
+ # Git worktrees
37
+ .worktrees/
aegro-0.2.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Aegro
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.
aegro-0.2.0/PKG-INFO ADDED
@@ -0,0 +1,240 @@
1
+ Metadata-Version: 2.4
2
+ Name: aegro
3
+ Version: 0.2.0
4
+ Summary: CLI for Aegro agricultural management API
5
+ Project-URL: Homepage, https://github.com/aegro/tool-aegro-cli
6
+ Project-URL: Repository, https://github.com/aegro/tool-aegro-cli.git
7
+ Project-URL: Issues, https://github.com/aegro/tool-aegro-cli/issues
8
+ Project-URL: Changelog, https://github.com/aegro/tool-aegro-cli/releases
9
+ Author-email: Aegro Engineering <pedro@aegro.com.br>
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: agriculture,api-client,cli,farm-management,typer
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Environment :: Console
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Scientific/Engineering
20
+ Classifier: Typing :: Typed
21
+ Requires-Python: >=3.11
22
+ Requires-Dist: httpx>=0.27.0
23
+ Requires-Dist: pydantic-settings>=2.0.0
24
+ Requires-Dist: pydantic>=2.0.0
25
+ Requires-Dist: structlog>=24.0.0
26
+ Requires-Dist: typer[all]>=0.12.0
27
+ Provides-Extra: dev
28
+ Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
29
+ Requires-Dist: pytest-httpx>=0.34.0; extra == 'dev'
30
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
31
+ Requires-Dist: ruff>=0.8.0; extra == 'dev'
32
+ Description-Content-Type: text/markdown
33
+
34
+ # Aegro CLI
35
+
36
+ Command-line interface for the [Aegro](https://aegro.com.br) agricultural management API.
37
+
38
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
39
+ [![PyPI](https://img.shields.io/pypi/v/aegro.svg)](https://pypi.org/project/aegro/)
40
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
41
+
42
+ ---
43
+
44
+ ## Install
45
+
46
+ ```bash
47
+ # pipx (recommended)
48
+ pipx install aegro
49
+
50
+ # uv
51
+ uv tool install aegro
52
+
53
+ # Homebrew (macOS)
54
+ brew tap aegro/tap
55
+ brew install aegro
56
+ ```
57
+
58
+ For development:
59
+
60
+ ```bash
61
+ git clone https://github.com/aegro/tool-aegro-cli.git
62
+ cd tool-aegro-cli
63
+ uv sync
64
+ uv run aegro --help
65
+ ```
66
+
67
+ ---
68
+
69
+ ## Quick Start
70
+
71
+ ```bash
72
+ # 1. Authenticate
73
+ aegro auth login --farm-name "Fazenda Sul" --api-key "aegro_abc123..."
74
+
75
+ # 2. Select a farm
76
+ aegro farms list
77
+ aegro farms select "Fazenda Sul"
78
+
79
+ # 3. Start working
80
+ aegro crops list --start-date 2025-01-01 --end-date 2025-12-31
81
+ aegro financial installments --status PENDING
82
+ aegro stock items --output table
83
+ ```
84
+
85
+ ---
86
+
87
+ ## Commands
88
+
89
+ | Group | Commands | Domain |
90
+ |-------|----------|--------|
91
+ | `auth` | login, status, logout | Authentication |
92
+ | `farms` | list, select, info | Farm management |
93
+ | `crops` | get, list, prorate, harvest-discounts, prorates, glebes | Harvest management |
94
+ | `activities` | get, list, plan, realizations, get-plan, get-realization, create-plan | Activity planning |
95
+ | `financial` | bill, installment, installments, create/update/delete-installment, realize | Accounts payable/receivable |
96
+ | `stock` | item, location, items, locations, logs, log, transfer, entry, removal | Inventory |
97
+ | `elements` | get, list, create-defensive/fertilizer/item/seed/service, set-categories | Inputs/supplies |
98
+ | `assets` | get, list, create-machine/vehicle/garner/immobilized/pivot/weather-station | Equipment |
99
+ | `fuel-supplies` | get, list, create, update | Fuel management |
100
+ | `maintenances` | get, list, create, update | Maintenance records |
101
+ | `harvest-logs` | get, create | Harvest records |
102
+ | `bank-accounts` | get, list, create | Bank accounts |
103
+ | `companies` | get, list, create | Suppliers/vendors |
104
+ | `fin-categories` | get, list, create, subcategories | Chart of accounts |
105
+ | `catalogs` | list, element-keys, elements | Catalog lookups |
106
+ | `tags` | get, list, create | Tags/labels |
107
+ | `weather` | get, create | Weather data |
108
+ | `purchase-orders` | get, list, create | Purchase orders |
109
+ | `glebes` | get, list | Farm fields |
110
+ | `crop-glebes` | get, list | Crop fields |
111
+
112
+ ---
113
+
114
+ ## Output Formats
115
+
116
+ All commands support three output formats:
117
+
118
+ ```bash
119
+ aegro crops list --output json # JSON (default, for LLMs/scripts)
120
+ aegro crops list --output table # Rich table for humans
121
+ aegro crops list --output csv # CSV export
122
+ ```
123
+
124
+ ---
125
+
126
+ ## Usage Examples
127
+
128
+ ### Human workflow
129
+
130
+ ```bash
131
+ # Morning overview
132
+ aegro farms select "Fazenda Norte"
133
+ aegro crops list --output table
134
+ aegro financial installments --status PENDING --due-date-start 2025-03-01 --output table
135
+ aegro stock items --output table
136
+
137
+ # Register a fuel supply
138
+ aegro fuel-supplies create --asset-key K --date 2025-03-13 --quantity 150 --unit L --cost 900
139
+
140
+ # Check harvest
141
+ aegro harvest-logs get <key>
142
+ ```
143
+
144
+ ### LLM/Agent workflow
145
+
146
+ ```bash
147
+ # Agents use JSON output (default) for structured data
148
+ aegro crops list --start-date 2025-01-01 --end-date 2025-12-31
149
+ aegro activities list --crop-key <key>
150
+ aegro stock items
151
+ aegro financial installments --status PENDING
152
+ ```
153
+
154
+ ---
155
+
156
+ ## AI Skills
157
+
158
+ The project includes guided workflows for AI assistants in `.claude/skills/`:
159
+
160
+ ### Domain skills (personas)
161
+
162
+ | Skill | Purpose |
163
+ |-------|---------|
164
+ | `aegro-agronomo` | Agronomic domain — crops, fields, activities, harvests, weather, inputs |
165
+ | `aegro-estoquista` | Stock domain — items, locations, movements, catalogs, elements |
166
+ | `aegro-financeiro` | Financial domain — bills, installments, categories, bank accounts, companies |
167
+ | `aegro-operacional` | Operational domain — farms, auth, tags, cross-domain orchestration |
168
+ | `aegro-patrimonial` | Asset domain — machines, vehicles, fuel supplies, maintenances |
169
+
170
+ ### Workflow skills
171
+
172
+ | Skill | Purpose |
173
+ |-------|---------|
174
+ | `aegro-visao-geral` | Farm overview dashboard |
175
+ | `aegro-fechamento-safra` | Crop season closing checklist |
176
+ | `aegro-lancamento-financeiro` | Financial entry guide |
177
+ | `aegro-reconciliacao-estoque` | Stock reconciliation |
178
+ | `aegro-monitoramento-pragas` | Pest monitoring |
179
+ | `aegro-analise-rentabilidade` | Profitability analysis |
180
+ | `aegro-cadastro-patrimonio` | Asset registration |
181
+
182
+ ---
183
+
184
+ ## Configuration
185
+
186
+ ### Authentication
187
+
188
+ Credential resolution priority:
189
+
190
+ 1. `AEGRO_FARMS` env var (JSON) — for CI/CD and scripts
191
+ 2. `AEGRO_FARMS_FILE` env var (path) — for Docker/K8s secrets
192
+ 3. `~/.config/aegro/credentials.json` — interactive setup via `aegro auth login`
193
+
194
+ ```bash
195
+ # Option 1: Environment variable
196
+ export AEGRO_FARMS='{"Fazenda Norte": "aegro_key1", "Fazenda Sul": "aegro_key2"}'
197
+
198
+ # Option 2: Interactive login (saves to ~/.config/aegro/credentials.json)
199
+ aegro auth login --farm-name "Fazenda Norte" --api-key "aegro_key1"
200
+ ```
201
+
202
+ ### Environment Variables
203
+
204
+ | Variable | Default | Purpose |
205
+ |----------|---------|---------|
206
+ | `AEGRO_API_BASE_URL` | `https://app.aegro.com.br` | Aegro API base URL |
207
+ | `AEGRO_FARMS` | — | JSON map of farm name → API key |
208
+ | `AEGRO_FARMS_FILE` | — | Path to JSON credentials file |
209
+
210
+ ---
211
+
212
+ ## Development
213
+
214
+ ```bash
215
+ # Install dependencies
216
+ uv sync
217
+
218
+ # Run tests
219
+ uv run pytest -v
220
+
221
+ # Lint
222
+ uv run ruff check aegro/ tests/
223
+
224
+ # Format
225
+ uv run ruff format aegro/ tests/
226
+ ```
227
+
228
+ ---
229
+
230
+ ## Links
231
+
232
+ - [Aegro](https://aegro.com.br) — Agricultural management platform
233
+ - [Typer](https://typer.tiangolo.com/) — CLI framework
234
+ - [PyPI: aegro](https://pypi.org/project/aegro/) — Package page
235
+
236
+ ---
237
+
238
+ ## License
239
+
240
+ [MIT](LICENSE)
aegro-0.2.0/README.md ADDED
@@ -0,0 +1,207 @@
1
+ # Aegro CLI
2
+
3
+ Command-line interface for the [Aegro](https://aegro.com.br) agricultural management API.
4
+
5
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
6
+ [![PyPI](https://img.shields.io/pypi/v/aegro.svg)](https://pypi.org/project/aegro/)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
+
9
+ ---
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ # pipx (recommended)
15
+ pipx install aegro
16
+
17
+ # uv
18
+ uv tool install aegro
19
+
20
+ # Homebrew (macOS)
21
+ brew tap aegro/tap
22
+ brew install aegro
23
+ ```
24
+
25
+ For development:
26
+
27
+ ```bash
28
+ git clone https://github.com/aegro/tool-aegro-cli.git
29
+ cd tool-aegro-cli
30
+ uv sync
31
+ uv run aegro --help
32
+ ```
33
+
34
+ ---
35
+
36
+ ## Quick Start
37
+
38
+ ```bash
39
+ # 1. Authenticate
40
+ aegro auth login --farm-name "Fazenda Sul" --api-key "aegro_abc123..."
41
+
42
+ # 2. Select a farm
43
+ aegro farms list
44
+ aegro farms select "Fazenda Sul"
45
+
46
+ # 3. Start working
47
+ aegro crops list --start-date 2025-01-01 --end-date 2025-12-31
48
+ aegro financial installments --status PENDING
49
+ aegro stock items --output table
50
+ ```
51
+
52
+ ---
53
+
54
+ ## Commands
55
+
56
+ | Group | Commands | Domain |
57
+ |-------|----------|--------|
58
+ | `auth` | login, status, logout | Authentication |
59
+ | `farms` | list, select, info | Farm management |
60
+ | `crops` | get, list, prorate, harvest-discounts, prorates, glebes | Harvest management |
61
+ | `activities` | get, list, plan, realizations, get-plan, get-realization, create-plan | Activity planning |
62
+ | `financial` | bill, installment, installments, create/update/delete-installment, realize | Accounts payable/receivable |
63
+ | `stock` | item, location, items, locations, logs, log, transfer, entry, removal | Inventory |
64
+ | `elements` | get, list, create-defensive/fertilizer/item/seed/service, set-categories | Inputs/supplies |
65
+ | `assets` | get, list, create-machine/vehicle/garner/immobilized/pivot/weather-station | Equipment |
66
+ | `fuel-supplies` | get, list, create, update | Fuel management |
67
+ | `maintenances` | get, list, create, update | Maintenance records |
68
+ | `harvest-logs` | get, create | Harvest records |
69
+ | `bank-accounts` | get, list, create | Bank accounts |
70
+ | `companies` | get, list, create | Suppliers/vendors |
71
+ | `fin-categories` | get, list, create, subcategories | Chart of accounts |
72
+ | `catalogs` | list, element-keys, elements | Catalog lookups |
73
+ | `tags` | get, list, create | Tags/labels |
74
+ | `weather` | get, create | Weather data |
75
+ | `purchase-orders` | get, list, create | Purchase orders |
76
+ | `glebes` | get, list | Farm fields |
77
+ | `crop-glebes` | get, list | Crop fields |
78
+
79
+ ---
80
+
81
+ ## Output Formats
82
+
83
+ All commands support three output formats:
84
+
85
+ ```bash
86
+ aegro crops list --output json # JSON (default, for LLMs/scripts)
87
+ aegro crops list --output table # Rich table for humans
88
+ aegro crops list --output csv # CSV export
89
+ ```
90
+
91
+ ---
92
+
93
+ ## Usage Examples
94
+
95
+ ### Human workflow
96
+
97
+ ```bash
98
+ # Morning overview
99
+ aegro farms select "Fazenda Norte"
100
+ aegro crops list --output table
101
+ aegro financial installments --status PENDING --due-date-start 2025-03-01 --output table
102
+ aegro stock items --output table
103
+
104
+ # Register a fuel supply
105
+ aegro fuel-supplies create --asset-key K --date 2025-03-13 --quantity 150 --unit L --cost 900
106
+
107
+ # Check harvest
108
+ aegro harvest-logs get <key>
109
+ ```
110
+
111
+ ### LLM/Agent workflow
112
+
113
+ ```bash
114
+ # Agents use JSON output (default) for structured data
115
+ aegro crops list --start-date 2025-01-01 --end-date 2025-12-31
116
+ aegro activities list --crop-key <key>
117
+ aegro stock items
118
+ aegro financial installments --status PENDING
119
+ ```
120
+
121
+ ---
122
+
123
+ ## AI Skills
124
+
125
+ The project includes guided workflows for AI assistants in `.claude/skills/`:
126
+
127
+ ### Domain skills (personas)
128
+
129
+ | Skill | Purpose |
130
+ |-------|---------|
131
+ | `aegro-agronomo` | Agronomic domain — crops, fields, activities, harvests, weather, inputs |
132
+ | `aegro-estoquista` | Stock domain — items, locations, movements, catalogs, elements |
133
+ | `aegro-financeiro` | Financial domain — bills, installments, categories, bank accounts, companies |
134
+ | `aegro-operacional` | Operational domain — farms, auth, tags, cross-domain orchestration |
135
+ | `aegro-patrimonial` | Asset domain — machines, vehicles, fuel supplies, maintenances |
136
+
137
+ ### Workflow skills
138
+
139
+ | Skill | Purpose |
140
+ |-------|---------|
141
+ | `aegro-visao-geral` | Farm overview dashboard |
142
+ | `aegro-fechamento-safra` | Crop season closing checklist |
143
+ | `aegro-lancamento-financeiro` | Financial entry guide |
144
+ | `aegro-reconciliacao-estoque` | Stock reconciliation |
145
+ | `aegro-monitoramento-pragas` | Pest monitoring |
146
+ | `aegro-analise-rentabilidade` | Profitability analysis |
147
+ | `aegro-cadastro-patrimonio` | Asset registration |
148
+
149
+ ---
150
+
151
+ ## Configuration
152
+
153
+ ### Authentication
154
+
155
+ Credential resolution priority:
156
+
157
+ 1. `AEGRO_FARMS` env var (JSON) — for CI/CD and scripts
158
+ 2. `AEGRO_FARMS_FILE` env var (path) — for Docker/K8s secrets
159
+ 3. `~/.config/aegro/credentials.json` — interactive setup via `aegro auth login`
160
+
161
+ ```bash
162
+ # Option 1: Environment variable
163
+ export AEGRO_FARMS='{"Fazenda Norte": "aegro_key1", "Fazenda Sul": "aegro_key2"}'
164
+
165
+ # Option 2: Interactive login (saves to ~/.config/aegro/credentials.json)
166
+ aegro auth login --farm-name "Fazenda Norte" --api-key "aegro_key1"
167
+ ```
168
+
169
+ ### Environment Variables
170
+
171
+ | Variable | Default | Purpose |
172
+ |----------|---------|---------|
173
+ | `AEGRO_API_BASE_URL` | `https://app.aegro.com.br` | Aegro API base URL |
174
+ | `AEGRO_FARMS` | — | JSON map of farm name → API key |
175
+ | `AEGRO_FARMS_FILE` | — | Path to JSON credentials file |
176
+
177
+ ---
178
+
179
+ ## Development
180
+
181
+ ```bash
182
+ # Install dependencies
183
+ uv sync
184
+
185
+ # Run tests
186
+ uv run pytest -v
187
+
188
+ # Lint
189
+ uv run ruff check aegro/ tests/
190
+
191
+ # Format
192
+ uv run ruff format aegro/ tests/
193
+ ```
194
+
195
+ ---
196
+
197
+ ## Links
198
+
199
+ - [Aegro](https://aegro.com.br) — Agricultural management platform
200
+ - [Typer](https://typer.tiangolo.com/) — CLI framework
201
+ - [PyPI: aegro](https://pypi.org/project/aegro/) — Package page
202
+
203
+ ---
204
+
205
+ ## License
206
+
207
+ [MIT](LICENSE)
@@ -0,0 +1,4 @@
1
+ try:
2
+ from aegro._version import __version__
3
+ except ImportError:
4
+ __version__ = "0.0.0+unknown"
@@ -0,0 +1,34 @@
1
+ # file generated by setuptools-scm
2
+ # don't change, don't track in version control
3
+
4
+ __all__ = [
5
+ "__version__",
6
+ "__version_tuple__",
7
+ "version",
8
+ "version_tuple",
9
+ "__commit_id__",
10
+ "commit_id",
11
+ ]
12
+
13
+ TYPE_CHECKING = False
14
+ if TYPE_CHECKING:
15
+ from typing import Tuple
16
+ from typing import Union
17
+
18
+ VERSION_TUPLE = Tuple[Union[int, str], ...]
19
+ COMMIT_ID = Union[str, None]
20
+ else:
21
+ VERSION_TUPLE = object
22
+ COMMIT_ID = object
23
+
24
+ version: str
25
+ __version__: str
26
+ __version_tuple__: VERSION_TUPLE
27
+ version_tuple: VERSION_TUPLE
28
+ commit_id: COMMIT_ID
29
+ __commit_id__: COMMIT_ID
30
+
31
+ __version__ = version = '0.2.0'
32
+ __version_tuple__ = version_tuple = (0, 2, 0)
33
+
34
+ __commit_id__ = commit_id = None
@@ -0,0 +1,128 @@
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+
5
+ import structlog
6
+ import httpx
7
+
8
+ from aegro.errors import AegroAPIError, translate_api_error
9
+
10
+ logger = structlog.get_logger()
11
+
12
+
13
+ class AegroClient:
14
+ def __init__(
15
+ self,
16
+ base_url: str = "https://app.aegro.com.br",
17
+ timeout: float = 30.0,
18
+ max_retries: int = 3,
19
+ ):
20
+ self._base_url = base_url.rstrip("/")
21
+ self._timeout = timeout
22
+ self._max_retries = max_retries
23
+ self._http: httpx.AsyncClient | None = None
24
+
25
+ def _get_http(self) -> httpx.AsyncClient:
26
+ if self._http is None or self._http.is_closed:
27
+ self._http = httpx.AsyncClient(timeout=self._timeout)
28
+ return self._http
29
+
30
+ async def close(self) -> None:
31
+ if self._http is not None and not self._http.is_closed:
32
+ await self._http.aclose()
33
+ self._http = None
34
+
35
+ def _headers(self, api_key: str) -> dict[str, str]:
36
+ return {
37
+ "Aegro-Public-API-Key": api_key,
38
+ "Accept": "application/json",
39
+ "Content-Type": "application/json",
40
+ }
41
+
42
+ async def _request(
43
+ self, method: str, path: str, api_key: str, json_body: dict | None = None
44
+ ) -> dict | list | None:
45
+ url = f"{self._base_url}{path}"
46
+ attempt = 0
47
+ last_response = None
48
+ http = self._get_http()
49
+
50
+ while attempt <= self._max_retries:
51
+ try:
52
+ response = await http.request(
53
+ method, url, headers=self._headers(api_key), json=json_body
54
+ )
55
+ last_response = response
56
+ if response.status_code == 204:
57
+ return None
58
+ if response.status_code in (200, 201):
59
+ return response.json()
60
+ if response.status_code >= 500 and attempt < self._max_retries:
61
+ attempt += 1
62
+ logger.warning(
63
+ "aegro_api_retry", path=path, status=response.status_code, attempt=attempt
64
+ )
65
+ await asyncio.sleep(2**attempt)
66
+ continue
67
+ body = {}
68
+ try:
69
+ body = response.json()
70
+ except Exception:
71
+ pass
72
+ raise translate_api_error(response.status_code, body)
73
+ except httpx.TimeoutException:
74
+ if attempt < self._max_retries:
75
+ attempt += 1
76
+ logger.warning("aegro_api_timeout", path=path, attempt=attempt)
77
+ await asyncio.sleep(2**attempt)
78
+ continue
79
+ raise AegroAPIError(
80
+ 504, "Timeout ao conectar com o servico Aegro. Tente novamente.", retryable=True
81
+ )
82
+ except AegroAPIError:
83
+ raise
84
+ except httpx.HTTPError as exc:
85
+ raise AegroAPIError(
86
+ 502,
87
+ f"Erro de conexao com o servico Aegro: {type(exc).__name__}",
88
+ retryable=True,
89
+ ) from exc
90
+
91
+ if last_response is not None:
92
+ body = {}
93
+ try:
94
+ body = last_response.json()
95
+ except Exception:
96
+ pass
97
+ raise translate_api_error(last_response.status_code, body)
98
+ raise AegroAPIError(502, "Erro inesperado de conexao.", retryable=True)
99
+
100
+ async def get(self, path: str, *, api_key: str) -> dict | list | None:
101
+ return await self._request("GET", path, api_key)
102
+
103
+ async def post(
104
+ self, path: str, *, api_key: str, json_body: dict | None = None
105
+ ) -> dict | list | None:
106
+ return await self._request("POST", path, api_key, json_body)
107
+
108
+ async def put(
109
+ self, path: str, *, api_key: str, json_body: dict | None = None
110
+ ) -> dict | list | None:
111
+ return await self._request("PUT", path, api_key, json_body)
112
+
113
+ async def delete(self, path: str, *, api_key: str) -> dict | list | None:
114
+ return await self._request("DELETE", path, api_key)
115
+
116
+ async def get_user_identity(self, api_key: str) -> str | None:
117
+ """Return the email address associated with the given API key.
118
+
119
+ Calls ``/pub/v1/users/me`` and extracts the ``email`` field.
120
+ Returns ``None`` when the endpoint does not return a usable email.
121
+ """
122
+ try:
123
+ data = await self.get("/pub/v1/users/me", api_key=api_key)
124
+ if isinstance(data, dict):
125
+ return data.get("email")
126
+ except (AegroAPIError, httpx.HTTPError):
127
+ logger.warning("identity_lookup_failed", exc_info=True)
128
+ return None