folyo 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.
- folyo-0.1.0/.gitignore +12 -0
- folyo-0.1.0/LICENSE +21 -0
- folyo-0.1.0/PKG-INFO +184 -0
- folyo-0.1.0/README.md +146 -0
- folyo-0.1.0/folyo/__init__.py +94 -0
- folyo-0.1.0/folyo/_redact.py +26 -0
- folyo-0.1.0/folyo/client.py +296 -0
- folyo-0.1.0/folyo/errors.py +144 -0
- folyo-0.1.0/folyo/models.py +433 -0
- folyo-0.1.0/folyo/py.typed +0 -0
- folyo-0.1.0/folyo/resources.py +600 -0
- folyo-0.1.0/pyproject.toml +70 -0
folyo-0.1.0/.gitignore
ADDED
folyo-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Folyo Technologies SpA
|
|
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.
|
folyo-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: folyo
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: SDK oficial de Python para la API de Folyo (facturacion electronica chilena, DTE + SII).
|
|
5
|
+
Project-URL: Homepage, https://folyo.cl
|
|
6
|
+
Project-URL: Documentation, https://api.folyo.cl/docs
|
|
7
|
+
Project-URL: Repository, https://github.com/SYCTecnologiaCo/Folyo
|
|
8
|
+
Project-URL: Issues, https://github.com/SYCTecnologiaCo/Folyo/issues
|
|
9
|
+
Author-email: Folyo <soporte@folyo.cl>
|
|
10
|
+
License: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: boleta,chile,dte,factura-electronica,facturacion,folyo,sii
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Topic :: Office/Business :: Financial :: Accounting
|
|
25
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
26
|
+
Classifier: Typing :: Typed
|
|
27
|
+
Requires-Python: >=3.9
|
|
28
|
+
Requires-Dist: httpx>=0.27
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: build>=1.2; extra == 'dev'
|
|
31
|
+
Requires-Dist: mypy>=1.11; extra == 'dev'
|
|
32
|
+
Requires-Dist: pip-audit>=2.7; extra == 'dev'
|
|
33
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
34
|
+
Requires-Dist: respx>=0.21; extra == 'dev'
|
|
35
|
+
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
36
|
+
Requires-Dist: twine>=5.1; extra == 'dev'
|
|
37
|
+
Description-Content-Type: text/markdown
|
|
38
|
+
|
|
39
|
+
# Folyo — SDK oficial de Python
|
|
40
|
+
|
|
41
|
+
SDK de Python para la API de [Folyo](https://folyo.cl): facturacion electronica
|
|
42
|
+
chilena (DTE + SII) standalone. Del codigo al SII, sin escalas.
|
|
43
|
+
|
|
44
|
+
- Cliente tipado sobre `httpx` (unica dependencia de runtime).
|
|
45
|
+
- Errores tipados con mapeo de los codigos del servidor.
|
|
46
|
+
- Soporte del patron de emision asincrona (encolar + polling con backoff).
|
|
47
|
+
- Idempotencia, override de ambiente del SII y reintentos seguros ante 429/503.
|
|
48
|
+
- Redaccion de secretos (la API key/JWT nunca aparecen en `repr` ni en errores).
|
|
49
|
+
|
|
50
|
+
## Instalacion
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install folyo
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Requiere Python 3.9 o superior.
|
|
57
|
+
|
|
58
|
+
## Autenticacion
|
|
59
|
+
|
|
60
|
+
El cliente exige exactamente uno de los dos esquemas:
|
|
61
|
+
|
|
62
|
+
- **API key** (recomendada para integraciones server-side, no expira). Se envia
|
|
63
|
+
como header `X-API-Key`. Fija el tenant y la empresa.
|
|
64
|
+
- **JWT Bearer** (sesion de usuario). Se envia como `Authorization: Bearer ...`.
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
from folyo import Folyo
|
|
68
|
+
|
|
69
|
+
# Con API key
|
|
70
|
+
folyo = Folyo(api_key="<tu-api-key>")
|
|
71
|
+
|
|
72
|
+
# O con un token JWT
|
|
73
|
+
folyo = Folyo(token="eyJhbGciOi...")
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Tambien funciona como context manager (cierra el cliente HTTP al salir):
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
with Folyo(api_key="<tu-api-key>") as folyo:
|
|
80
|
+
...
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Quickstart: emitir una Factura Electronica (DTE 33)
|
|
84
|
+
|
|
85
|
+
La emision es **asincrona**: `emitir()` encola y devuelve un `job_id`; el helper
|
|
86
|
+
`emitir_y_esperar()` hace el polling por ti hasta que el job termina.
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
import uuid
|
|
90
|
+
from folyo import Folyo, DTERequest, Receptor, DetalleLinea
|
|
91
|
+
|
|
92
|
+
with Folyo(api_key="<tu-api-key>") as folyo:
|
|
93
|
+
req = DTERequest(
|
|
94
|
+
tipo_dte=33, # Factura Electronica
|
|
95
|
+
receptor=Receptor(
|
|
96
|
+
rut="12.345.678-9",
|
|
97
|
+
razon_social="Cliente SpA",
|
|
98
|
+
giro="Comercio",
|
|
99
|
+
),
|
|
100
|
+
detalle=[
|
|
101
|
+
DetalleLinea(nombre="Servicio de consultoria", monto=100000),
|
|
102
|
+
],
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
# Encolar y esperar el resultado (con Idempotency-Key para reintentar seguro)
|
|
106
|
+
job = folyo.dte.emitir_y_esperar(req, idempotency_key=str(uuid.uuid4()))
|
|
107
|
+
|
|
108
|
+
if job.estado == "completed" and job.result is not None:
|
|
109
|
+
print("Folio:", job.result.folio)
|
|
110
|
+
print("Track ID:", job.result.track_id)
|
|
111
|
+
print("Total:", job.result.monto_total)
|
|
112
|
+
|
|
113
|
+
# Descargar el PDF
|
|
114
|
+
pdf = folyo.dte.descargar_pdf(33, job.result.folio)
|
|
115
|
+
with open(f"factura-{job.result.folio}.pdf", "wb") as f:
|
|
116
|
+
f.write(pdf)
|
|
117
|
+
else:
|
|
118
|
+
print("La emision fallo:", job.estado)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Si prefieres resolver el resultado por webhook o SSE, usa `emitir()` directo:
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
encolada = folyo.dte.emitir(req)
|
|
125
|
+
print(encolada.job_id) # resuelve luego via webhook dte.emitido o polling
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Manejo de errores
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
from folyo import (
|
|
132
|
+
Folyo,
|
|
133
|
+
FolyoAuthError,
|
|
134
|
+
FolyoQuotaError,
|
|
135
|
+
FolyoRateLimitError,
|
|
136
|
+
FolyoValidationError,
|
|
137
|
+
FolyoSiiUnavailableError,
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
try:
|
|
141
|
+
folyo.dte.emitir(req)
|
|
142
|
+
except FolyoRateLimitError as e:
|
|
143
|
+
print("Reintentar en", e.retry_after, "segundos")
|
|
144
|
+
except FolyoQuotaError as e:
|
|
145
|
+
print("Limite de plan o pago requerido:", e.code)
|
|
146
|
+
except FolyoAuthError:
|
|
147
|
+
print("Credenciales invalidas o sin permisos")
|
|
148
|
+
except FolyoValidationError as e:
|
|
149
|
+
print("Datos invalidos:", e.message)
|
|
150
|
+
except FolyoSiiUnavailableError:
|
|
151
|
+
print("El SII no esta disponible, reintenta mas tarde")
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
El SDK reintenta automaticamente (con backoff exponencial y respetando
|
|
155
|
+
`Retry-After`) ante `429` y `503` en operaciones seguras: peticiones `GET` y
|
|
156
|
+
emisiones con `Idempotency-Key`.
|
|
157
|
+
|
|
158
|
+
## Recursos disponibles
|
|
159
|
+
|
|
160
|
+
| Recurso | Metodos principales |
|
|
161
|
+
|---|---|
|
|
162
|
+
| `folyo.dte` | `emitir`, `get_emision`, `emitir_y_esperar`, `listar_documentos`, `descargar_xml`, `descargar_pdf`, `regenerar_pdf`, `consultar_estado`, `consultar_envio`, `emitidos`, `recibidos`, `contribuyente`, `situacion_tributaria`, `enviar_rcof`, `resumen_rcof` |
|
|
163
|
+
| `folyo.folios` | `info`, `solicitar` |
|
|
164
|
+
| `folyo.rcv` | `periodos`, `periodo`, `sync`, `resumen_iva` |
|
|
165
|
+
| `folyo.clientes` | `listar`, `upsert`, `importar`, `buscar`, `actualizar`, `eliminar` |
|
|
166
|
+
| `folyo.empresa` | `listar`, `seleccionar` |
|
|
167
|
+
| `folyo.acuse` | `registrar`, `pendientes`, `estado` |
|
|
168
|
+
| `folyo.webhooks` | `listar`, `crear`, `actualizar`, `eliminar` |
|
|
169
|
+
| `folyo.api_keys` | `listar`, `crear`, `eliminar` |
|
|
170
|
+
|
|
171
|
+
Algunos endpoints (clientes, RCV, listado de documentos) requieren "panel
|
|
172
|
+
operativo" y responden `403` en planes solo-API.
|
|
173
|
+
|
|
174
|
+
## Seguridad
|
|
175
|
+
|
|
176
|
+
- La API key y el JWT nunca se incluyen en `repr(cliente)` ni en los errores.
|
|
177
|
+
- Los errores exponen solo el mensaje sanitizado del servidor, el codigo
|
|
178
|
+
estable, el status HTTP y el `request_id`: nunca el cuerpo de la respuesta
|
|
179
|
+
(que puede traer datos sensibles como el XML firmado o secrets de webhook).
|
|
180
|
+
- El SDK no escribe logs por defecto.
|
|
181
|
+
|
|
182
|
+
## Licencia
|
|
183
|
+
|
|
184
|
+
MIT. Ver [LICENSE](./LICENSE).
|
folyo-0.1.0/README.md
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# Folyo — SDK oficial de Python
|
|
2
|
+
|
|
3
|
+
SDK de Python para la API de [Folyo](https://folyo.cl): facturacion electronica
|
|
4
|
+
chilena (DTE + SII) standalone. Del codigo al SII, sin escalas.
|
|
5
|
+
|
|
6
|
+
- Cliente tipado sobre `httpx` (unica dependencia de runtime).
|
|
7
|
+
- Errores tipados con mapeo de los codigos del servidor.
|
|
8
|
+
- Soporte del patron de emision asincrona (encolar + polling con backoff).
|
|
9
|
+
- Idempotencia, override de ambiente del SII y reintentos seguros ante 429/503.
|
|
10
|
+
- Redaccion de secretos (la API key/JWT nunca aparecen en `repr` ni en errores).
|
|
11
|
+
|
|
12
|
+
## Instalacion
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pip install folyo
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Requiere Python 3.9 o superior.
|
|
19
|
+
|
|
20
|
+
## Autenticacion
|
|
21
|
+
|
|
22
|
+
El cliente exige exactamente uno de los dos esquemas:
|
|
23
|
+
|
|
24
|
+
- **API key** (recomendada para integraciones server-side, no expira). Se envia
|
|
25
|
+
como header `X-API-Key`. Fija el tenant y la empresa.
|
|
26
|
+
- **JWT Bearer** (sesion de usuario). Se envia como `Authorization: Bearer ...`.
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
from folyo import Folyo
|
|
30
|
+
|
|
31
|
+
# Con API key
|
|
32
|
+
folyo = Folyo(api_key="<tu-api-key>")
|
|
33
|
+
|
|
34
|
+
# O con un token JWT
|
|
35
|
+
folyo = Folyo(token="eyJhbGciOi...")
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Tambien funciona como context manager (cierra el cliente HTTP al salir):
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
with Folyo(api_key="<tu-api-key>") as folyo:
|
|
42
|
+
...
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Quickstart: emitir una Factura Electronica (DTE 33)
|
|
46
|
+
|
|
47
|
+
La emision es **asincrona**: `emitir()` encola y devuelve un `job_id`; el helper
|
|
48
|
+
`emitir_y_esperar()` hace el polling por ti hasta que el job termina.
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
import uuid
|
|
52
|
+
from folyo import Folyo, DTERequest, Receptor, DetalleLinea
|
|
53
|
+
|
|
54
|
+
with Folyo(api_key="<tu-api-key>") as folyo:
|
|
55
|
+
req = DTERequest(
|
|
56
|
+
tipo_dte=33, # Factura Electronica
|
|
57
|
+
receptor=Receptor(
|
|
58
|
+
rut="12.345.678-9",
|
|
59
|
+
razon_social="Cliente SpA",
|
|
60
|
+
giro="Comercio",
|
|
61
|
+
),
|
|
62
|
+
detalle=[
|
|
63
|
+
DetalleLinea(nombre="Servicio de consultoria", monto=100000),
|
|
64
|
+
],
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
# Encolar y esperar el resultado (con Idempotency-Key para reintentar seguro)
|
|
68
|
+
job = folyo.dte.emitir_y_esperar(req, idempotency_key=str(uuid.uuid4()))
|
|
69
|
+
|
|
70
|
+
if job.estado == "completed" and job.result is not None:
|
|
71
|
+
print("Folio:", job.result.folio)
|
|
72
|
+
print("Track ID:", job.result.track_id)
|
|
73
|
+
print("Total:", job.result.monto_total)
|
|
74
|
+
|
|
75
|
+
# Descargar el PDF
|
|
76
|
+
pdf = folyo.dte.descargar_pdf(33, job.result.folio)
|
|
77
|
+
with open(f"factura-{job.result.folio}.pdf", "wb") as f:
|
|
78
|
+
f.write(pdf)
|
|
79
|
+
else:
|
|
80
|
+
print("La emision fallo:", job.estado)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Si prefieres resolver el resultado por webhook o SSE, usa `emitir()` directo:
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
encolada = folyo.dte.emitir(req)
|
|
87
|
+
print(encolada.job_id) # resuelve luego via webhook dte.emitido o polling
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Manejo de errores
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
from folyo import (
|
|
94
|
+
Folyo,
|
|
95
|
+
FolyoAuthError,
|
|
96
|
+
FolyoQuotaError,
|
|
97
|
+
FolyoRateLimitError,
|
|
98
|
+
FolyoValidationError,
|
|
99
|
+
FolyoSiiUnavailableError,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
try:
|
|
103
|
+
folyo.dte.emitir(req)
|
|
104
|
+
except FolyoRateLimitError as e:
|
|
105
|
+
print("Reintentar en", e.retry_after, "segundos")
|
|
106
|
+
except FolyoQuotaError as e:
|
|
107
|
+
print("Limite de plan o pago requerido:", e.code)
|
|
108
|
+
except FolyoAuthError:
|
|
109
|
+
print("Credenciales invalidas o sin permisos")
|
|
110
|
+
except FolyoValidationError as e:
|
|
111
|
+
print("Datos invalidos:", e.message)
|
|
112
|
+
except FolyoSiiUnavailableError:
|
|
113
|
+
print("El SII no esta disponible, reintenta mas tarde")
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
El SDK reintenta automaticamente (con backoff exponencial y respetando
|
|
117
|
+
`Retry-After`) ante `429` y `503` en operaciones seguras: peticiones `GET` y
|
|
118
|
+
emisiones con `Idempotency-Key`.
|
|
119
|
+
|
|
120
|
+
## Recursos disponibles
|
|
121
|
+
|
|
122
|
+
| Recurso | Metodos principales |
|
|
123
|
+
|---|---|
|
|
124
|
+
| `folyo.dte` | `emitir`, `get_emision`, `emitir_y_esperar`, `listar_documentos`, `descargar_xml`, `descargar_pdf`, `regenerar_pdf`, `consultar_estado`, `consultar_envio`, `emitidos`, `recibidos`, `contribuyente`, `situacion_tributaria`, `enviar_rcof`, `resumen_rcof` |
|
|
125
|
+
| `folyo.folios` | `info`, `solicitar` |
|
|
126
|
+
| `folyo.rcv` | `periodos`, `periodo`, `sync`, `resumen_iva` |
|
|
127
|
+
| `folyo.clientes` | `listar`, `upsert`, `importar`, `buscar`, `actualizar`, `eliminar` |
|
|
128
|
+
| `folyo.empresa` | `listar`, `seleccionar` |
|
|
129
|
+
| `folyo.acuse` | `registrar`, `pendientes`, `estado` |
|
|
130
|
+
| `folyo.webhooks` | `listar`, `crear`, `actualizar`, `eliminar` |
|
|
131
|
+
| `folyo.api_keys` | `listar`, `crear`, `eliminar` |
|
|
132
|
+
|
|
133
|
+
Algunos endpoints (clientes, RCV, listado de documentos) requieren "panel
|
|
134
|
+
operativo" y responden `403` en planes solo-API.
|
|
135
|
+
|
|
136
|
+
## Seguridad
|
|
137
|
+
|
|
138
|
+
- La API key y el JWT nunca se incluyen en `repr(cliente)` ni en los errores.
|
|
139
|
+
- Los errores exponen solo el mensaje sanitizado del servidor, el codigo
|
|
140
|
+
estable, el status HTTP y el `request_id`: nunca el cuerpo de la respuesta
|
|
141
|
+
(que puede traer datos sensibles como el XML firmado o secrets de webhook).
|
|
142
|
+
- El SDK no escribe logs por defecto.
|
|
143
|
+
|
|
144
|
+
## Licencia
|
|
145
|
+
|
|
146
|
+
MIT. Ver [LICENSE](./LICENSE).
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"""SDK oficial de Python para la API de Folyo.
|
|
2
|
+
|
|
3
|
+
Folyo es facturacion electronica chilena (DTE + SII). Este SDK envuelve la API
|
|
4
|
+
REST de ``https://api.folyo.cl`` con un cliente tipado, manejo de errores y
|
|
5
|
+
soporte para el patron de emision asincrona.
|
|
6
|
+
|
|
7
|
+
Ejemplo minimo::
|
|
8
|
+
|
|
9
|
+
from folyo import Folyo, DTERequest, Receptor, DetalleLinea
|
|
10
|
+
|
|
11
|
+
with Folyo(api_key="<tu-api-key>") as folyo:
|
|
12
|
+
req = DTERequest(
|
|
13
|
+
tipo_dte=33,
|
|
14
|
+
receptor=Receptor(rut="12.345.678-9", razon_social="Cliente SpA"),
|
|
15
|
+
detalle=[DetalleLinea(nombre="Servicio", monto=100000)],
|
|
16
|
+
)
|
|
17
|
+
job = folyo.dte.emitir_y_esperar(req)
|
|
18
|
+
print(job.result.folio)
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
from ._redact import redact
|
|
24
|
+
from .client import DEFAULT_BASE_URL, USER_AGENT, Folyo, __version__
|
|
25
|
+
from .errors import (
|
|
26
|
+
FolyoAuthError,
|
|
27
|
+
FolyoConflictError,
|
|
28
|
+
FolyoConnectionError,
|
|
29
|
+
FolyoError,
|
|
30
|
+
FolyoNotFoundError,
|
|
31
|
+
FolyoQuotaError,
|
|
32
|
+
FolyoRateLimitError,
|
|
33
|
+
FolyoSiiUnavailableError,
|
|
34
|
+
FolyoValidationError,
|
|
35
|
+
)
|
|
36
|
+
from .models import (
|
|
37
|
+
AcuseRequest,
|
|
38
|
+
ApiKey,
|
|
39
|
+
ApiKeyCreated,
|
|
40
|
+
AuthTokens,
|
|
41
|
+
Cliente,
|
|
42
|
+
DescuentoGlobal,
|
|
43
|
+
DetalleLinea,
|
|
44
|
+
Documento,
|
|
45
|
+
DTERequest,
|
|
46
|
+
EmisionEncolada,
|
|
47
|
+
EmisionJob,
|
|
48
|
+
EmisionResult,
|
|
49
|
+
Empresa,
|
|
50
|
+
FoliosInfo,
|
|
51
|
+
Receptor,
|
|
52
|
+
Referencia,
|
|
53
|
+
Transporte,
|
|
54
|
+
Webhook,
|
|
55
|
+
WebhookCreated,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
__all__ = [
|
|
59
|
+
"__version__",
|
|
60
|
+
"DEFAULT_BASE_URL",
|
|
61
|
+
"USER_AGENT",
|
|
62
|
+
"Folyo",
|
|
63
|
+
"redact",
|
|
64
|
+
# Errores
|
|
65
|
+
"FolyoError",
|
|
66
|
+
"FolyoAuthError",
|
|
67
|
+
"FolyoQuotaError",
|
|
68
|
+
"FolyoValidationError",
|
|
69
|
+
"FolyoNotFoundError",
|
|
70
|
+
"FolyoConflictError",
|
|
71
|
+
"FolyoRateLimitError",
|
|
72
|
+
"FolyoSiiUnavailableError",
|
|
73
|
+
"FolyoConnectionError",
|
|
74
|
+
# Modelos
|
|
75
|
+
"DTERequest",
|
|
76
|
+
"Receptor",
|
|
77
|
+
"DetalleLinea",
|
|
78
|
+
"DescuentoGlobal",
|
|
79
|
+
"Referencia",
|
|
80
|
+
"Transporte",
|
|
81
|
+
"EmisionEncolada",
|
|
82
|
+
"EmisionResult",
|
|
83
|
+
"EmisionJob",
|
|
84
|
+
"Documento",
|
|
85
|
+
"FoliosInfo",
|
|
86
|
+
"Cliente",
|
|
87
|
+
"Empresa",
|
|
88
|
+
"Webhook",
|
|
89
|
+
"WebhookCreated",
|
|
90
|
+
"ApiKey",
|
|
91
|
+
"ApiKeyCreated",
|
|
92
|
+
"AcuseRequest",
|
|
93
|
+
"AuthTokens",
|
|
94
|
+
]
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""Utilidades de redaccion de secretos.
|
|
2
|
+
|
|
3
|
+
El SDK no debe filtrar credenciales en ``repr``, logs ni telemetria. Esta
|
|
4
|
+
funcion enmascara cualquier valor sensible mostrando solo una pista minima.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import Optional
|
|
10
|
+
|
|
11
|
+
__all__ = ["redact"]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def redact(value: Optional[str]) -> str:
|
|
15
|
+
"""Devuelve una version enmascarada y segura de un secreto.
|
|
16
|
+
|
|
17
|
+
- ``None`` o cadena vacia -> ``"None"``.
|
|
18
|
+
- Valores cortos -> ``"***"`` (sin pistas, no hay suficiente entropia).
|
|
19
|
+
- Valores largos -> primeros 4 caracteres + ``"***"`` (ej. ``"stri***"``),
|
|
20
|
+
util para distinguir keys sin revelar el secreto.
|
|
21
|
+
"""
|
|
22
|
+
if not value:
|
|
23
|
+
return "None"
|
|
24
|
+
if len(value) <= 8:
|
|
25
|
+
return "***"
|
|
26
|
+
return f"{value[:4]}***"
|