agrobr 0.1.2__py3-none-any.whl → 0.5.0__py3-none-any.whl
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/__init__.py +3 -2
- agrobr/benchmark/__init__.py +343 -0
- agrobr/cache/policies.py +3 -8
- agrobr/cepea/api.py +87 -30
- agrobr/cepea/client.py +0 -7
- agrobr/cli.py +141 -5
- agrobr/conab/api.py +72 -6
- agrobr/config.py +137 -0
- agrobr/constants.py +1 -2
- agrobr/contracts/__init__.py +186 -0
- agrobr/contracts/cepea.py +80 -0
- agrobr/contracts/conab.py +181 -0
- agrobr/contracts/ibge.py +146 -0
- agrobr/export.py +251 -0
- agrobr/health/__init__.py +10 -0
- agrobr/health/doctor.py +321 -0
- agrobr/http/browser.py +0 -9
- agrobr/ibge/api.py +104 -25
- agrobr/ibge/client.py +5 -20
- agrobr/models.py +100 -1
- agrobr/noticias_agricolas/client.py +0 -7
- agrobr/noticias_agricolas/parser.py +0 -17
- agrobr/plugins/__init__.py +205 -0
- agrobr/quality.py +319 -0
- agrobr/sla.py +249 -0
- agrobr/snapshots.py +321 -0
- agrobr/stability.py +148 -0
- agrobr/validators/semantic.py +447 -0
- {agrobr-0.1.2.dist-info → agrobr-0.5.0.dist-info}/METADATA +12 -12
- {agrobr-0.1.2.dist-info → agrobr-0.5.0.dist-info}/RECORD +33 -19
- {agrobr-0.1.2.dist-info → agrobr-0.5.0.dist-info}/WHEEL +0 -0
- {agrobr-0.1.2.dist-info → agrobr-0.5.0.dist-info}/entry_points.txt +0 -0
- {agrobr-0.1.2.dist-info → agrobr-0.5.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"""Stability Contracts para garantia de schema e compatibilidade."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from enum import StrEnum
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
import pandas as pd
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ColumnType(StrEnum):
|
|
13
|
+
"""Tipos de dados suportados nos contratos."""
|
|
14
|
+
|
|
15
|
+
DATE = "date"
|
|
16
|
+
DATETIME = "datetime"
|
|
17
|
+
STRING = "str"
|
|
18
|
+
INTEGER = "int"
|
|
19
|
+
FLOAT = "float"
|
|
20
|
+
DECIMAL = "Decimal"
|
|
21
|
+
BOOLEAN = "bool"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class BreakingChangePolicy(StrEnum):
|
|
25
|
+
"""Politica para mudancas que quebram contrato."""
|
|
26
|
+
|
|
27
|
+
MAJOR_VERSION = "major"
|
|
28
|
+
NEVER = "never"
|
|
29
|
+
DEPRECATE_FIRST = "deprecate"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@dataclass
|
|
33
|
+
class Column:
|
|
34
|
+
"""Definicao de uma coluna no contrato."""
|
|
35
|
+
|
|
36
|
+
name: str
|
|
37
|
+
type: ColumnType
|
|
38
|
+
nullable: bool = False
|
|
39
|
+
unit: str | None = None
|
|
40
|
+
description: str = ""
|
|
41
|
+
stable: bool = True
|
|
42
|
+
deprecated: bool = False
|
|
43
|
+
deprecated_in: str | None = None
|
|
44
|
+
removed_in: str | None = None
|
|
45
|
+
|
|
46
|
+
def validate(self, series: pd.Series) -> list[str]:
|
|
47
|
+
"""Valida uma serie contra esta definicao."""
|
|
48
|
+
errors = []
|
|
49
|
+
|
|
50
|
+
if not self.nullable and series.isna().any():
|
|
51
|
+
null_count = series.isna().sum()
|
|
52
|
+
errors.append(f"Column '{self.name}' has {null_count} null values but nullable=False")
|
|
53
|
+
|
|
54
|
+
if self.type == ColumnType.DATE:
|
|
55
|
+
if not pd.api.types.is_datetime64_any_dtype(series):
|
|
56
|
+
try:
|
|
57
|
+
pd.to_datetime(series.dropna())
|
|
58
|
+
except Exception:
|
|
59
|
+
errors.append(f"Column '{self.name}' cannot be converted to date")
|
|
60
|
+
|
|
61
|
+
elif self.type == ColumnType.INTEGER:
|
|
62
|
+
if not pd.api.types.is_integer_dtype(series):
|
|
63
|
+
non_null = series.dropna()
|
|
64
|
+
if len(non_null) > 0:
|
|
65
|
+
try:
|
|
66
|
+
non_null.astype(int)
|
|
67
|
+
except (ValueError, TypeError):
|
|
68
|
+
errors.append(f"Column '{self.name}' contains non-integer values")
|
|
69
|
+
|
|
70
|
+
elif self.type in (
|
|
71
|
+
ColumnType.FLOAT,
|
|
72
|
+
ColumnType.DECIMAL,
|
|
73
|
+
) and not pd.api.types.is_numeric_dtype(series):
|
|
74
|
+
errors.append(f"Column '{self.name}' is not numeric")
|
|
75
|
+
|
|
76
|
+
return errors
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@dataclass
|
|
80
|
+
class Contract:
|
|
81
|
+
"""Contrato de estabilidade para um dataset."""
|
|
82
|
+
|
|
83
|
+
name: str
|
|
84
|
+
version: str
|
|
85
|
+
columns: list[Column]
|
|
86
|
+
guarantees: list[str] = field(default_factory=list)
|
|
87
|
+
breaking_policy: BreakingChangePolicy = BreakingChangePolicy.MAJOR_VERSION
|
|
88
|
+
effective_from: str = ""
|
|
89
|
+
|
|
90
|
+
def validate(self, df: pd.DataFrame) -> tuple[bool, list[str]]:
|
|
91
|
+
"""
|
|
92
|
+
Valida DataFrame contra o contrato.
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
df: DataFrame a validar
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
Tupla (valido, lista de erros)
|
|
99
|
+
"""
|
|
100
|
+
errors = []
|
|
101
|
+
|
|
102
|
+
required_cols = [c.name for c in self.columns if not c.nullable and c.stable]
|
|
103
|
+
missing = set(required_cols) - set(df.columns)
|
|
104
|
+
if missing:
|
|
105
|
+
errors.append(f"Missing required columns: {missing}")
|
|
106
|
+
|
|
107
|
+
for col_def in self.columns:
|
|
108
|
+
if col_def.name in df.columns:
|
|
109
|
+
col_errors = col_def.validate(df[col_def.name])
|
|
110
|
+
errors.extend(col_errors)
|
|
111
|
+
|
|
112
|
+
return len(errors) == 0, errors
|
|
113
|
+
|
|
114
|
+
def get_column(self, name: str) -> Column | None:
|
|
115
|
+
"""Retorna definicao de uma coluna pelo nome."""
|
|
116
|
+
for col in self.columns:
|
|
117
|
+
if col.name == name:
|
|
118
|
+
return col
|
|
119
|
+
return None
|
|
120
|
+
|
|
121
|
+
def list_columns(self, stable_only: bool = False) -> list[str]:
|
|
122
|
+
"""Lista nomes das colunas."""
|
|
123
|
+
if stable_only:
|
|
124
|
+
return [c.name for c in self.columns if c.stable]
|
|
125
|
+
return [c.name for c in self.columns]
|
|
126
|
+
|
|
127
|
+
def to_markdown(self) -> str:
|
|
128
|
+
"""Gera documentacao Markdown do contrato."""
|
|
129
|
+
lines = [
|
|
130
|
+
f"# Contract: {self.name}",
|
|
131
|
+
f"**Version:** {self.version}",
|
|
132
|
+
f"**Effective from:** {self.effective_from}",
|
|
133
|
+
f"**Breaking policy:** {self.breaking_policy.value}",
|
|
134
|
+
"",
|
|
135
|
+
"## Columns",
|
|
136
|
+
"",
|
|
137
|
+
"| Column | Type | Nullable | Unit | Stable | Description |",
|
|
138
|
+
"|--------|------|----------|------|--------|-------------|",
|
|
139
|
+
]
|
|
140
|
+
|
|
141
|
+
for col in self.columns:
|
|
142
|
+
stable = "Yes" if col.stable else "No"
|
|
143
|
+
nullable = "Yes" if col.nullable else "No"
|
|
144
|
+
unit = col.unit or "-"
|
|
145
|
+
desc = col.description or "-"
|
|
146
|
+
deprecated = " (deprecated)" if col.deprecated else ""
|
|
147
|
+
lines.append(
|
|
148
|
+
f"| {col.name}{deprecated} | {col.type.value} | {nullable} | {unit} | {stable} | {desc} |"
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
if self.guarantees:
|
|
152
|
+
lines.extend(["", "## Guarantees", ""])
|
|
153
|
+
for g in self.guarantees:
|
|
154
|
+
lines.append(f"- {g}")
|
|
155
|
+
|
|
156
|
+
return "\n".join(lines)
|
|
157
|
+
|
|
158
|
+
def to_dict(self) -> dict[str, Any]:
|
|
159
|
+
"""Converte contrato para dicionario."""
|
|
160
|
+
return {
|
|
161
|
+
"name": self.name,
|
|
162
|
+
"version": self.version,
|
|
163
|
+
"effective_from": self.effective_from,
|
|
164
|
+
"breaking_policy": self.breaking_policy.value,
|
|
165
|
+
"columns": [
|
|
166
|
+
{
|
|
167
|
+
"name": c.name,
|
|
168
|
+
"type": c.type.value,
|
|
169
|
+
"nullable": c.nullable,
|
|
170
|
+
"unit": c.unit,
|
|
171
|
+
"stable": c.stable,
|
|
172
|
+
"deprecated": c.deprecated,
|
|
173
|
+
"description": c.description,
|
|
174
|
+
}
|
|
175
|
+
for c in self.columns
|
|
176
|
+
],
|
|
177
|
+
"guarantees": self.guarantees,
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
__all__ = [
|
|
182
|
+
"Column",
|
|
183
|
+
"ColumnType",
|
|
184
|
+
"Contract",
|
|
185
|
+
"BreakingChangePolicy",
|
|
186
|
+
]
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"""Contratos de estabilidade para dados CEPEA."""
|
|
2
|
+
|
|
3
|
+
from agrobr.contracts import BreakingChangePolicy, Column, ColumnType, Contract
|
|
4
|
+
|
|
5
|
+
CEPEA_INDICADOR_V1 = Contract(
|
|
6
|
+
name="cepea.indicador",
|
|
7
|
+
version="1.0",
|
|
8
|
+
effective_from="0.3.0",
|
|
9
|
+
columns=[
|
|
10
|
+
Column(
|
|
11
|
+
name="data",
|
|
12
|
+
type=ColumnType.DATE,
|
|
13
|
+
nullable=False,
|
|
14
|
+
stable=True,
|
|
15
|
+
description="Data do indicador",
|
|
16
|
+
),
|
|
17
|
+
Column(
|
|
18
|
+
name="produto",
|
|
19
|
+
type=ColumnType.STRING,
|
|
20
|
+
nullable=False,
|
|
21
|
+
stable=True,
|
|
22
|
+
description="Nome do produto (soja, milho, etc)",
|
|
23
|
+
),
|
|
24
|
+
Column(
|
|
25
|
+
name="praca",
|
|
26
|
+
type=ColumnType.STRING,
|
|
27
|
+
nullable=True,
|
|
28
|
+
stable=True,
|
|
29
|
+
description="Praca de referencia",
|
|
30
|
+
),
|
|
31
|
+
Column(
|
|
32
|
+
name="valor",
|
|
33
|
+
type=ColumnType.FLOAT,
|
|
34
|
+
nullable=False,
|
|
35
|
+
unit="BRL",
|
|
36
|
+
stable=True,
|
|
37
|
+
description="Preco em reais",
|
|
38
|
+
),
|
|
39
|
+
Column(
|
|
40
|
+
name="unidade",
|
|
41
|
+
type=ColumnType.STRING,
|
|
42
|
+
nullable=False,
|
|
43
|
+
stable=True,
|
|
44
|
+
description="Unidade do preco (BRL/sc60kg, BRL/@, etc)",
|
|
45
|
+
),
|
|
46
|
+
Column(
|
|
47
|
+
name="fonte",
|
|
48
|
+
type=ColumnType.STRING,
|
|
49
|
+
nullable=False,
|
|
50
|
+
stable=True,
|
|
51
|
+
description="Fonte dos dados",
|
|
52
|
+
),
|
|
53
|
+
Column(
|
|
54
|
+
name="metodologia",
|
|
55
|
+
type=ColumnType.STRING,
|
|
56
|
+
nullable=True,
|
|
57
|
+
stable=False,
|
|
58
|
+
description="Descricao da metodologia",
|
|
59
|
+
),
|
|
60
|
+
Column(
|
|
61
|
+
name="anomalies",
|
|
62
|
+
type=ColumnType.STRING,
|
|
63
|
+
nullable=True,
|
|
64
|
+
stable=False,
|
|
65
|
+
description="Lista de anomalias detectadas",
|
|
66
|
+
),
|
|
67
|
+
],
|
|
68
|
+
guarantees=[
|
|
69
|
+
"Column names never change (additions only)",
|
|
70
|
+
"Types only widen (int -> float, str -> categorical)",
|
|
71
|
+
"Dates always in local timezone (Sao Paulo)",
|
|
72
|
+
"Units explicit in 'unidade' column",
|
|
73
|
+
"'valor' is always positive",
|
|
74
|
+
"'data' is always a valid business day",
|
|
75
|
+
],
|
|
76
|
+
breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
__all__ = ["CEPEA_INDICADOR_V1"]
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"""Contratos de estabilidade para dados CONAB."""
|
|
2
|
+
|
|
3
|
+
from agrobr.contracts import BreakingChangePolicy, Column, ColumnType, Contract
|
|
4
|
+
|
|
5
|
+
CONAB_SAFRA_V1 = Contract(
|
|
6
|
+
name="conab.safras",
|
|
7
|
+
version="1.0",
|
|
8
|
+
effective_from="0.3.0",
|
|
9
|
+
columns=[
|
|
10
|
+
Column(
|
|
11
|
+
name="fonte",
|
|
12
|
+
type=ColumnType.STRING,
|
|
13
|
+
nullable=False,
|
|
14
|
+
stable=True,
|
|
15
|
+
description="Fonte dos dados (conab)",
|
|
16
|
+
),
|
|
17
|
+
Column(
|
|
18
|
+
name="produto",
|
|
19
|
+
type=ColumnType.STRING,
|
|
20
|
+
nullable=False,
|
|
21
|
+
stable=True,
|
|
22
|
+
description="Nome do produto",
|
|
23
|
+
),
|
|
24
|
+
Column(
|
|
25
|
+
name="safra",
|
|
26
|
+
type=ColumnType.STRING,
|
|
27
|
+
nullable=False,
|
|
28
|
+
stable=True,
|
|
29
|
+
description="Safra no formato YYYY/YY",
|
|
30
|
+
),
|
|
31
|
+
Column(
|
|
32
|
+
name="uf",
|
|
33
|
+
type=ColumnType.STRING,
|
|
34
|
+
nullable=True,
|
|
35
|
+
stable=True,
|
|
36
|
+
description="Sigla da UF",
|
|
37
|
+
),
|
|
38
|
+
Column(
|
|
39
|
+
name="area_plantada",
|
|
40
|
+
type=ColumnType.FLOAT,
|
|
41
|
+
nullable=True,
|
|
42
|
+
unit="mil_ha",
|
|
43
|
+
stable=True,
|
|
44
|
+
description="Area plantada em mil hectares",
|
|
45
|
+
),
|
|
46
|
+
Column(
|
|
47
|
+
name="area_colhida",
|
|
48
|
+
type=ColumnType.FLOAT,
|
|
49
|
+
nullable=True,
|
|
50
|
+
unit="mil_ha",
|
|
51
|
+
stable=True,
|
|
52
|
+
description="Area colhida em mil hectares",
|
|
53
|
+
),
|
|
54
|
+
Column(
|
|
55
|
+
name="produtividade",
|
|
56
|
+
type=ColumnType.FLOAT,
|
|
57
|
+
nullable=True,
|
|
58
|
+
unit="kg/ha",
|
|
59
|
+
stable=True,
|
|
60
|
+
description="Produtividade em kg/ha",
|
|
61
|
+
),
|
|
62
|
+
Column(
|
|
63
|
+
name="producao",
|
|
64
|
+
type=ColumnType.FLOAT,
|
|
65
|
+
nullable=True,
|
|
66
|
+
unit="mil_ton",
|
|
67
|
+
stable=True,
|
|
68
|
+
description="Producao em mil toneladas",
|
|
69
|
+
),
|
|
70
|
+
Column(
|
|
71
|
+
name="levantamento",
|
|
72
|
+
type=ColumnType.INTEGER,
|
|
73
|
+
nullable=False,
|
|
74
|
+
stable=True,
|
|
75
|
+
description="Numero do levantamento (1-12)",
|
|
76
|
+
),
|
|
77
|
+
Column(
|
|
78
|
+
name="data_publicacao",
|
|
79
|
+
type=ColumnType.DATE,
|
|
80
|
+
nullable=False,
|
|
81
|
+
stable=True,
|
|
82
|
+
description="Data de publicacao do levantamento",
|
|
83
|
+
),
|
|
84
|
+
],
|
|
85
|
+
guarantees=[
|
|
86
|
+
"Column names never change (additions only)",
|
|
87
|
+
"'safra' always matches pattern YYYY/YY",
|
|
88
|
+
"'uf' is always a valid Brazilian state code",
|
|
89
|
+
"'levantamento' is between 1 and 12",
|
|
90
|
+
"Numeric values are always >= 0",
|
|
91
|
+
],
|
|
92
|
+
breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
CONAB_BALANCO_V1 = Contract(
|
|
96
|
+
name="conab.balanco",
|
|
97
|
+
version="1.0",
|
|
98
|
+
effective_from="0.3.0",
|
|
99
|
+
columns=[
|
|
100
|
+
Column(
|
|
101
|
+
name="produto",
|
|
102
|
+
type=ColumnType.STRING,
|
|
103
|
+
nullable=False,
|
|
104
|
+
stable=True,
|
|
105
|
+
description="Nome do produto",
|
|
106
|
+
),
|
|
107
|
+
Column(
|
|
108
|
+
name="safra",
|
|
109
|
+
type=ColumnType.STRING,
|
|
110
|
+
nullable=False,
|
|
111
|
+
stable=True,
|
|
112
|
+
description="Safra de referencia",
|
|
113
|
+
),
|
|
114
|
+
Column(
|
|
115
|
+
name="estoque_inicial",
|
|
116
|
+
type=ColumnType.FLOAT,
|
|
117
|
+
nullable=True,
|
|
118
|
+
unit="mil_ton",
|
|
119
|
+
stable=True,
|
|
120
|
+
description="Estoque inicial",
|
|
121
|
+
),
|
|
122
|
+
Column(
|
|
123
|
+
name="producao",
|
|
124
|
+
type=ColumnType.FLOAT,
|
|
125
|
+
nullable=True,
|
|
126
|
+
unit="mil_ton",
|
|
127
|
+
stable=True,
|
|
128
|
+
description="Producao",
|
|
129
|
+
),
|
|
130
|
+
Column(
|
|
131
|
+
name="importacao",
|
|
132
|
+
type=ColumnType.FLOAT,
|
|
133
|
+
nullable=True,
|
|
134
|
+
unit="mil_ton",
|
|
135
|
+
stable=True,
|
|
136
|
+
description="Importacao",
|
|
137
|
+
),
|
|
138
|
+
Column(
|
|
139
|
+
name="suprimento",
|
|
140
|
+
type=ColumnType.FLOAT,
|
|
141
|
+
nullable=True,
|
|
142
|
+
unit="mil_ton",
|
|
143
|
+
stable=True,
|
|
144
|
+
description="Suprimento total",
|
|
145
|
+
),
|
|
146
|
+
Column(
|
|
147
|
+
name="consumo",
|
|
148
|
+
type=ColumnType.FLOAT,
|
|
149
|
+
nullable=True,
|
|
150
|
+
unit="mil_ton",
|
|
151
|
+
stable=True,
|
|
152
|
+
description="Consumo interno",
|
|
153
|
+
),
|
|
154
|
+
Column(
|
|
155
|
+
name="exportacao",
|
|
156
|
+
type=ColumnType.FLOAT,
|
|
157
|
+
nullable=True,
|
|
158
|
+
unit="mil_ton",
|
|
159
|
+
stable=True,
|
|
160
|
+
description="Exportacao",
|
|
161
|
+
),
|
|
162
|
+
Column(
|
|
163
|
+
name="estoque_final",
|
|
164
|
+
type=ColumnType.FLOAT,
|
|
165
|
+
nullable=True,
|
|
166
|
+
unit="mil_ton",
|
|
167
|
+
stable=True,
|
|
168
|
+
description="Estoque final",
|
|
169
|
+
),
|
|
170
|
+
],
|
|
171
|
+
guarantees=[
|
|
172
|
+
"Column names never change (additions only)",
|
|
173
|
+
"All numeric values represent thousands of tons",
|
|
174
|
+
"suprimento = estoque_inicial + producao + importacao",
|
|
175
|
+
"estoque_final = suprimento - consumo - exportacao",
|
|
176
|
+
],
|
|
177
|
+
breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
__all__ = ["CONAB_SAFRA_V1", "CONAB_BALANCO_V1"]
|
agrobr/contracts/ibge.py
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"""Contratos de estabilidade para dados IBGE."""
|
|
2
|
+
|
|
3
|
+
from agrobr.contracts import BreakingChangePolicy, Column, ColumnType, Contract
|
|
4
|
+
|
|
5
|
+
IBGE_PAM_V1 = Contract(
|
|
6
|
+
name="ibge.pam",
|
|
7
|
+
version="1.0",
|
|
8
|
+
effective_from="0.3.0",
|
|
9
|
+
columns=[
|
|
10
|
+
Column(
|
|
11
|
+
name="ano",
|
|
12
|
+
type=ColumnType.INTEGER,
|
|
13
|
+
nullable=False,
|
|
14
|
+
stable=True,
|
|
15
|
+
description="Ano de referencia",
|
|
16
|
+
),
|
|
17
|
+
Column(
|
|
18
|
+
name="localidade",
|
|
19
|
+
type=ColumnType.STRING,
|
|
20
|
+
nullable=True,
|
|
21
|
+
stable=True,
|
|
22
|
+
description="Nome da localidade (UF ou municipio)",
|
|
23
|
+
),
|
|
24
|
+
Column(
|
|
25
|
+
name="produto",
|
|
26
|
+
type=ColumnType.STRING,
|
|
27
|
+
nullable=False,
|
|
28
|
+
stable=True,
|
|
29
|
+
description="Nome do produto",
|
|
30
|
+
),
|
|
31
|
+
Column(
|
|
32
|
+
name="area_plantada",
|
|
33
|
+
type=ColumnType.FLOAT,
|
|
34
|
+
nullable=True,
|
|
35
|
+
unit="ha",
|
|
36
|
+
stable=True,
|
|
37
|
+
description="Area plantada em hectares",
|
|
38
|
+
),
|
|
39
|
+
Column(
|
|
40
|
+
name="area_colhida",
|
|
41
|
+
type=ColumnType.FLOAT,
|
|
42
|
+
nullable=True,
|
|
43
|
+
unit="ha",
|
|
44
|
+
stable=True,
|
|
45
|
+
description="Area colhida em hectares",
|
|
46
|
+
),
|
|
47
|
+
Column(
|
|
48
|
+
name="producao",
|
|
49
|
+
type=ColumnType.FLOAT,
|
|
50
|
+
nullable=True,
|
|
51
|
+
unit="ton",
|
|
52
|
+
stable=True,
|
|
53
|
+
description="Quantidade produzida em toneladas",
|
|
54
|
+
),
|
|
55
|
+
Column(
|
|
56
|
+
name="rendimento",
|
|
57
|
+
type=ColumnType.FLOAT,
|
|
58
|
+
nullable=True,
|
|
59
|
+
unit="kg/ha",
|
|
60
|
+
stable=True,
|
|
61
|
+
description="Rendimento medio em kg/ha",
|
|
62
|
+
),
|
|
63
|
+
Column(
|
|
64
|
+
name="valor_producao",
|
|
65
|
+
type=ColumnType.FLOAT,
|
|
66
|
+
nullable=True,
|
|
67
|
+
unit="mil_reais",
|
|
68
|
+
stable=True,
|
|
69
|
+
description="Valor da producao em mil reais",
|
|
70
|
+
),
|
|
71
|
+
Column(
|
|
72
|
+
name="fonte",
|
|
73
|
+
type=ColumnType.STRING,
|
|
74
|
+
nullable=False,
|
|
75
|
+
stable=True,
|
|
76
|
+
description="Fonte dos dados (ibge_pam)",
|
|
77
|
+
),
|
|
78
|
+
],
|
|
79
|
+
guarantees=[
|
|
80
|
+
"Column names never change (additions only)",
|
|
81
|
+
"'ano' is always a valid year (>= 1974)",
|
|
82
|
+
"Numeric values are always >= 0",
|
|
83
|
+
"'fonte' is always 'ibge_pam'",
|
|
84
|
+
],
|
|
85
|
+
breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
IBGE_LSPA_V1 = Contract(
|
|
89
|
+
name="ibge.lspa",
|
|
90
|
+
version="1.0",
|
|
91
|
+
effective_from="0.3.0",
|
|
92
|
+
columns=[
|
|
93
|
+
Column(
|
|
94
|
+
name="ano",
|
|
95
|
+
type=ColumnType.INTEGER,
|
|
96
|
+
nullable=False,
|
|
97
|
+
stable=True,
|
|
98
|
+
description="Ano de referencia",
|
|
99
|
+
),
|
|
100
|
+
Column(
|
|
101
|
+
name="mes",
|
|
102
|
+
type=ColumnType.INTEGER,
|
|
103
|
+
nullable=True,
|
|
104
|
+
stable=True,
|
|
105
|
+
description="Mes de referencia (1-12)",
|
|
106
|
+
),
|
|
107
|
+
Column(
|
|
108
|
+
name="produto",
|
|
109
|
+
type=ColumnType.STRING,
|
|
110
|
+
nullable=False,
|
|
111
|
+
stable=True,
|
|
112
|
+
description="Nome do produto",
|
|
113
|
+
),
|
|
114
|
+
Column(
|
|
115
|
+
name="variavel",
|
|
116
|
+
type=ColumnType.STRING,
|
|
117
|
+
nullable=True,
|
|
118
|
+
stable=False,
|
|
119
|
+
description="Nome da variavel",
|
|
120
|
+
),
|
|
121
|
+
Column(
|
|
122
|
+
name="valor",
|
|
123
|
+
type=ColumnType.FLOAT,
|
|
124
|
+
nullable=True,
|
|
125
|
+
stable=False,
|
|
126
|
+
description="Valor da variavel",
|
|
127
|
+
),
|
|
128
|
+
Column(
|
|
129
|
+
name="fonte",
|
|
130
|
+
type=ColumnType.STRING,
|
|
131
|
+
nullable=False,
|
|
132
|
+
stable=True,
|
|
133
|
+
description="Fonte dos dados (ibge_lspa)",
|
|
134
|
+
),
|
|
135
|
+
],
|
|
136
|
+
guarantees=[
|
|
137
|
+
"Column names never change (additions only)",
|
|
138
|
+
"'ano' is always a valid year",
|
|
139
|
+
"'mes' is between 1 and 12 when present",
|
|
140
|
+
"'fonte' is always 'ibge_lspa'",
|
|
141
|
+
],
|
|
142
|
+
breaking_policy=BreakingChangePolicy.MAJOR_VERSION,
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
__all__ = ["IBGE_PAM_V1", "IBGE_LSPA_V1"]
|