catalogmx 0.3.0__py3-none-any.whl → 0.4.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.
- catalogmx/__init__.py +133 -19
- catalogmx/calculators/__init__.py +113 -0
- catalogmx/calculators/costo_trabajador.py +213 -0
- catalogmx/calculators/impuestos.py +920 -0
- catalogmx/calculators/imss.py +370 -0
- catalogmx/calculators/isr.py +290 -0
- catalogmx/calculators/resico.py +154 -0
- catalogmx/catalogs/banxico/__init__.py +29 -3
- catalogmx/catalogs/banxico/cetes_sqlite.py +279 -0
- catalogmx/catalogs/banxico/inflacion_sqlite.py +302 -0
- catalogmx/catalogs/banxico/salarios_minimos_sqlite.py +295 -0
- catalogmx/catalogs/banxico/tiie_sqlite.py +279 -0
- catalogmx/catalogs/banxico/tipo_cambio_usd_sqlite.py +255 -0
- catalogmx/catalogs/banxico/udis_sqlite.py +332 -0
- catalogmx/catalogs/cnbv/__init__.py +9 -0
- catalogmx/catalogs/cnbv/sectores.py +173 -0
- catalogmx/catalogs/conapo/__init__.py +15 -0
- catalogmx/catalogs/conapo/sistema_urbano_nacional.py +50 -0
- catalogmx/catalogs/conapo/zonas_metropolitanas.py +230 -0
- catalogmx/catalogs/ift/__init__.py +1 -1
- catalogmx/catalogs/ift/codigos_lada.py +517 -313
- catalogmx/catalogs/inegi/__init__.py +17 -0
- catalogmx/catalogs/inegi/scian.py +127 -0
- catalogmx/catalogs/mexico/__init__.py +2 -0
- catalogmx/catalogs/mexico/giros_mercantiles.py +119 -0
- catalogmx/catalogs/sat/carta_porte/material_peligroso.py +5 -1
- catalogmx/catalogs/sat/cfdi_4/clave_prod_serv.py +78 -0
- catalogmx/catalogs/sat/cfdi_4/tasa_o_cuota.py +2 -1
- catalogmx/catalogs/sepomex/__init__.py +2 -1
- catalogmx/catalogs/sepomex/codigos_postales.py +30 -2
- catalogmx/catalogs/sepomex/codigos_postales_completo.py +261 -0
- catalogmx/cli.py +12 -9
- catalogmx/data/__init__.py +10 -0
- catalogmx/data/mexico_dynamic.sqlite3 +0 -0
- catalogmx/data/updater.py +362 -0
- catalogmx/generators/__init__.py +20 -0
- catalogmx/generators/identity.py +582 -0
- catalogmx/helpers.py +177 -3
- catalogmx/utils/__init__.py +29 -0
- catalogmx/utils/clabe_utils.py +417 -0
- catalogmx/utils/text.py +7 -1
- catalogmx/validators/clabe.py +52 -2
- catalogmx/validators/nss.py +32 -27
- catalogmx/validators/rfc.py +185 -52
- catalogmx-0.4.0.dist-info/METADATA +905 -0
- {catalogmx-0.3.0.dist-info → catalogmx-0.4.0.dist-info}/RECORD +51 -25
- {catalogmx-0.3.0.dist-info → catalogmx-0.4.0.dist-info}/WHEEL +1 -1
- catalogmx/catalogs/banxico/udis.py +0 -279
- catalogmx-0.3.0.dist-info/METADATA +0 -644
- {catalogmx-0.3.0.dist-info → catalogmx-0.4.0.dist-info}/entry_points.txt +0 -0
- {catalogmx-0.3.0.dist-info → catalogmx-0.4.0.dist-info}/licenses/AUTHORS.rst +0 -0
- {catalogmx-0.3.0.dist-info → catalogmx-0.4.0.dist-info}/licenses/LICENSE +0 -0
- {catalogmx-0.3.0.dist-info → catalogmx-0.4.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Catálogo de Zonas Metropolitanas de México 2020
|
|
3
|
+
|
|
4
|
+
Fuente: SEDATU/INEGI/CONAPO - Metrópolis de México 2020
|
|
5
|
+
https://www.datos.gob.mx/dataset/metropolis_mexico_2020
|
|
6
|
+
|
|
7
|
+
Contiene 92 metrópolis conformadas por 421 municipios:
|
|
8
|
+
- 48 zonas metropolitanas (345 municipios)
|
|
9
|
+
- 22 metrópolis municipales
|
|
10
|
+
- 22 zonas conurbadas (54 municipios)
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import csv
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ZonasMetropolitanasCatalog:
|
|
18
|
+
"""Catálogo de Zonas Metropolitanas de México 2020"""
|
|
19
|
+
|
|
20
|
+
_data: list[dict] | None = None
|
|
21
|
+
_by_clave: dict[str, dict] | None = None
|
|
22
|
+
_by_municipio: dict[str, list[dict]] | None = None
|
|
23
|
+
_metropolis: dict[str, dict] | None = None
|
|
24
|
+
|
|
25
|
+
@classmethod
|
|
26
|
+
def _load_data(cls) -> None:
|
|
27
|
+
"""Carga los datos del catálogo"""
|
|
28
|
+
if cls._data is not None:
|
|
29
|
+
return
|
|
30
|
+
|
|
31
|
+
data_path = (
|
|
32
|
+
Path(__file__).resolve().parents[4]
|
|
33
|
+
/ "shared-data"
|
|
34
|
+
/ "conapo"
|
|
35
|
+
/ "municipios_tipologia.csv"
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
cls._data = []
|
|
39
|
+
cls._by_clave = {}
|
|
40
|
+
cls._by_municipio = {}
|
|
41
|
+
cls._metropolis = {}
|
|
42
|
+
|
|
43
|
+
with open(data_path, encoding="utf-8") as f:
|
|
44
|
+
reader = csv.DictReader(f)
|
|
45
|
+
for row in reader:
|
|
46
|
+
# Normalizar claves INEGI
|
|
47
|
+
cve_ent = str(row["clave_entidad"]).zfill(2)
|
|
48
|
+
cve_mun = str(row["clave_municipio"]).zfill(3)
|
|
49
|
+
cve_compuesta = f"{cve_ent}{cve_mun}"
|
|
50
|
+
|
|
51
|
+
record = {
|
|
52
|
+
"clave_metropoli": row["clave_metropoli"],
|
|
53
|
+
"tipo": row["tipo"],
|
|
54
|
+
"nombre_metropoli": row["nombre"],
|
|
55
|
+
"cve_entidad": cve_ent,
|
|
56
|
+
"entidad": row["entidad"],
|
|
57
|
+
"cve_municipio": cve_mun,
|
|
58
|
+
"cve_inegi": cve_compuesta,
|
|
59
|
+
"municipio": row["municipio"],
|
|
60
|
+
"es_central": (
|
|
61
|
+
row.get("centrales_conurbacion_fisica") == "True"
|
|
62
|
+
or row.get("centrales_integracion_funcional") == "True"
|
|
63
|
+
or row.get("centrales_capital_200khab") == "True"
|
|
64
|
+
or row.get("centrales_0100khab") == "True"
|
|
65
|
+
or row.get("centrales_50khab") == "True"
|
|
66
|
+
),
|
|
67
|
+
"es_exterior": (
|
|
68
|
+
row.get("exteriores_integracion_funcional") == "True"
|
|
69
|
+
or row.get("exteriores_continuidad_geografica") == "True"
|
|
70
|
+
),
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
cls._data.append(record)
|
|
74
|
+
cls._by_clave[cve_compuesta] = record
|
|
75
|
+
|
|
76
|
+
# Index by municipio
|
|
77
|
+
if cve_compuesta not in cls._by_municipio:
|
|
78
|
+
cls._by_municipio[cve_compuesta] = []
|
|
79
|
+
cls._by_municipio[cve_compuesta].append(record)
|
|
80
|
+
|
|
81
|
+
# Build metropolis index
|
|
82
|
+
clave_m = row["clave_metropoli"]
|
|
83
|
+
if clave_m not in cls._metropolis:
|
|
84
|
+
cls._metropolis[clave_m] = {
|
|
85
|
+
"clave": clave_m,
|
|
86
|
+
"nombre": row["nombre"],
|
|
87
|
+
"tipo": row["tipo"],
|
|
88
|
+
"municipios": [],
|
|
89
|
+
}
|
|
90
|
+
cls._metropolis[clave_m]["municipios"].append(record)
|
|
91
|
+
|
|
92
|
+
@classmethod
|
|
93
|
+
def get_all(cls) -> list[dict]:
|
|
94
|
+
"""Obtiene todos los registros de municipios metropolitanos"""
|
|
95
|
+
cls._load_data()
|
|
96
|
+
return cls._data.copy() if cls._data else []
|
|
97
|
+
|
|
98
|
+
@classmethod
|
|
99
|
+
def get_metropolis(cls) -> list[dict]:
|
|
100
|
+
"""Obtiene lista de todas las metrópolis"""
|
|
101
|
+
cls._load_data()
|
|
102
|
+
if not cls._metropolis:
|
|
103
|
+
return []
|
|
104
|
+
return [
|
|
105
|
+
{
|
|
106
|
+
"clave": m["clave"],
|
|
107
|
+
"nombre": m["nombre"],
|
|
108
|
+
"tipo": m["tipo"],
|
|
109
|
+
"num_municipios": len(m["municipios"]),
|
|
110
|
+
}
|
|
111
|
+
for m in cls._metropolis.values()
|
|
112
|
+
]
|
|
113
|
+
|
|
114
|
+
@classmethod
|
|
115
|
+
def get_por_tipo(cls, tipo: str) -> list[dict]:
|
|
116
|
+
"""
|
|
117
|
+
Obtiene metrópolis por tipo.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
tipo: 'Zona metropolitana', 'Metrópoli municipal', 'Zona conurbada'
|
|
121
|
+
"""
|
|
122
|
+
cls._load_data()
|
|
123
|
+
if not cls._metropolis:
|
|
124
|
+
return []
|
|
125
|
+
return [
|
|
126
|
+
{
|
|
127
|
+
"clave": m["clave"],
|
|
128
|
+
"nombre": m["nombre"],
|
|
129
|
+
"tipo": m["tipo"],
|
|
130
|
+
"num_municipios": len(m["municipios"]),
|
|
131
|
+
}
|
|
132
|
+
for m in cls._metropolis.values()
|
|
133
|
+
if m["tipo"] == tipo
|
|
134
|
+
]
|
|
135
|
+
|
|
136
|
+
@classmethod
|
|
137
|
+
def buscar_por_municipio(cls, cve_entidad: str, cve_municipio: str) -> dict | None:
|
|
138
|
+
"""
|
|
139
|
+
Busca si un municipio pertenece a alguna metrópolis.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
cve_entidad: Clave de entidad INEGI (01-32)
|
|
143
|
+
cve_municipio: Clave de municipio INEGI (001-570)
|
|
144
|
+
|
|
145
|
+
Returns:
|
|
146
|
+
Dict con información de la metrópolis o None
|
|
147
|
+
"""
|
|
148
|
+
cls._load_data()
|
|
149
|
+
cve = f"{cve_entidad.zfill(2)}{cve_municipio.zfill(3)}"
|
|
150
|
+
records = cls._by_municipio.get(cve, []) if cls._by_municipio else []
|
|
151
|
+
return records[0] if records else None
|
|
152
|
+
|
|
153
|
+
@classmethod
|
|
154
|
+
def get_municipios_de_metropoli(cls, clave_metropoli: str) -> list[dict]:
|
|
155
|
+
"""
|
|
156
|
+
Obtiene todos los municipios de una metrópolis.
|
|
157
|
+
|
|
158
|
+
Args:
|
|
159
|
+
clave_metropoli: Clave de la metrópolis (ej: "01.1.01")
|
|
160
|
+
|
|
161
|
+
Returns:
|
|
162
|
+
Lista de municipios con sus datos INEGI
|
|
163
|
+
"""
|
|
164
|
+
cls._load_data()
|
|
165
|
+
if not cls._metropolis:
|
|
166
|
+
return []
|
|
167
|
+
m = cls._metropolis.get(clave_metropoli)
|
|
168
|
+
return m["municipios"].copy() if m else []
|
|
169
|
+
|
|
170
|
+
@classmethod
|
|
171
|
+
def buscar_por_nombre(cls, nombre: str) -> list[dict]:
|
|
172
|
+
"""
|
|
173
|
+
Busca metrópolis por nombre (búsqueda parcial).
|
|
174
|
+
|
|
175
|
+
Args:
|
|
176
|
+
nombre: Nombre o parte del nombre de la metrópolis
|
|
177
|
+
|
|
178
|
+
Returns:
|
|
179
|
+
Lista de metrópolis que coinciden
|
|
180
|
+
"""
|
|
181
|
+
cls._load_data()
|
|
182
|
+
if not cls._metropolis:
|
|
183
|
+
return []
|
|
184
|
+
nombre_upper = nombre.upper()
|
|
185
|
+
return [
|
|
186
|
+
{
|
|
187
|
+
"clave": m["clave"],
|
|
188
|
+
"nombre": m["nombre"],
|
|
189
|
+
"tipo": m["tipo"],
|
|
190
|
+
"num_municipios": len(m["municipios"]),
|
|
191
|
+
}
|
|
192
|
+
for m in cls._metropolis.values()
|
|
193
|
+
if nombre_upper in m["nombre"].upper()
|
|
194
|
+
]
|
|
195
|
+
|
|
196
|
+
@classmethod
|
|
197
|
+
def es_municipio_metropolitano(cls, cve_entidad: str, cve_municipio: str) -> bool:
|
|
198
|
+
"""
|
|
199
|
+
Verifica si un municipio pertenece a alguna metrópolis.
|
|
200
|
+
|
|
201
|
+
Args:
|
|
202
|
+
cve_entidad: Clave de entidad INEGI
|
|
203
|
+
cve_municipio: Clave de municipio INEGI
|
|
204
|
+
|
|
205
|
+
Returns:
|
|
206
|
+
True si el municipio es metropolitano
|
|
207
|
+
"""
|
|
208
|
+
return cls.buscar_por_municipio(cve_entidad, cve_municipio) is not None
|
|
209
|
+
|
|
210
|
+
@classmethod
|
|
211
|
+
def get_estadisticas(cls) -> dict:
|
|
212
|
+
"""Obtiene estadísticas del catálogo"""
|
|
213
|
+
cls._load_data()
|
|
214
|
+
|
|
215
|
+
if not cls._data or not cls._metropolis:
|
|
216
|
+
return {}
|
|
217
|
+
|
|
218
|
+
tipos = {}
|
|
219
|
+
for m in cls._metropolis.values():
|
|
220
|
+
t = m["tipo"]
|
|
221
|
+
if t not in tipos:
|
|
222
|
+
tipos[t] = {"metropolis": 0, "municipios": 0}
|
|
223
|
+
tipos[t]["metropolis"] += 1
|
|
224
|
+
tipos[t]["municipios"] += len(m["municipios"])
|
|
225
|
+
|
|
226
|
+
return {
|
|
227
|
+
"total_metropolis": len(cls._metropolis),
|
|
228
|
+
"total_municipios": len(cls._data),
|
|
229
|
+
"por_tipo": tipos,
|
|
230
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
catalogmx.catalogs.ift - Catálogos del IFT
|
|
3
3
|
|
|
4
4
|
Catálogos del Instituto Federal de Telecomunicaciones:
|
|
5
|
-
- CodigosLADACatalog:
|
|
5
|
+
- CodigosLADACatalog: Códigos LADA con mapeo geográfico INEGI
|
|
6
6
|
- OperadoresMovilesCatalog: Operadores de telefonía móvil
|
|
7
7
|
"""
|
|
8
8
|
|