libredte-lib-sdk 0.1.0__tar.gz → 0.3.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.
- {libredte_lib_sdk-0.1.0 → libredte_lib_sdk-0.3.0}/.github/workflows/ci.yml +4 -1
- libredte_lib_sdk-0.3.0/.github/workflows/docs.yml +43 -0
- libredte_lib_sdk-0.3.0/.gitignore +21 -0
- libredte_lib_sdk-0.3.0/.readthedocs.yaml +26 -0
- libredte_lib_sdk-0.3.0/CLAUDE.md +37 -0
- libredte_lib_sdk-0.3.0/LICENSE +21 -0
- {libredte_lib_sdk-0.1.0 → libredte_lib_sdk-0.3.0}/Makefile +10 -2
- libredte_lib_sdk-0.3.0/PKG-INFO +272 -0
- {libredte_lib_sdk-0.1.0 → libredte_lib_sdk-0.3.0}/README.rst +68 -38
- libredte_lib_sdk-0.3.0/docs/Makefile +20 -0
- libredte_lib_sdk-0.3.0/docs/conf.py +31 -0
- libredte_lib_sdk-0.3.0/docs/index.rst +14 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/__init__.py +18 -0
- {libredte_lib_sdk-0.1.0 → libredte_lib_sdk-0.3.0}/libredte_lib_sdk/billing/__init__.py +9 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/billing/book/__init__.py +31 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/billing/book/builder.py +42 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/billing/book/loader.py +42 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/billing/book/models.py +70 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/billing/book/validator.py +51 -0
- {libredte_lib_sdk-0.1.0 → libredte_lib_sdk-0.3.0}/libredte_lib_sdk/billing/common.py +5 -2
- {libredte_lib_sdk-0.1.0 → libredte_lib_sdk-0.3.0}/libredte_lib_sdk/billing/document/__init__.py +22 -8
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/billing/document/builder.py +83 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/billing/document/dispatcher.py +106 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/billing/document/examples.py +41 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/billing/document/loader.py +31 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/billing/document/models.py +226 -0
- {libredte_lib_sdk-0.1.0 → libredte_lib_sdk-0.3.0}/libredte_lib_sdk/billing/document/renderer.py +21 -9
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/billing/document/validator.py +70 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/billing/enums.py +22 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/billing/exchange/__init__.py +25 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/billing/exchange/document_response.py +121 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/billing/exchange/models.py +55 -0
- {libredte_lib_sdk-0.1.0 → libredte_lib_sdk-0.3.0}/libredte_lib_sdk/billing/identifier/__init__.py +3 -0
- {libredte_lib_sdk-0.1.0 → libredte_lib_sdk-0.3.0}/libredte_lib_sdk/billing/identifier/caf_faker.py +6 -4
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/billing/identifier/caf_loader.py +29 -0
- {libredte_lib_sdk-0.1.0 → libredte_lib_sdk-0.3.0}/libredte_lib_sdk/billing/identifier/caf_validator.py +6 -7
- {libredte_lib_sdk-0.1.0 → libredte_lib_sdk-0.3.0}/libredte_lib_sdk/billing/identifier/models.py +3 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/billing/integration/__init__.py +52 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/billing/integration/models.py +253 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/billing/integration/sii_dte.py +192 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/billing/integration/sii_rcv.py +137 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/billing/integration/sii_rtc.py +56 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/billing/ownership_transfer/__init__.py +24 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/billing/ownership_transfer/aec.py +91 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/billing/ownership_transfer/models.py +31 -0
- {libredte_lib_sdk-0.1.0 → libredte_lib_sdk-0.3.0}/libredte_lib_sdk/billing/trading_parties/__init__.py +5 -1
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/billing/trading_parties/mandatario_manager.py +54 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/billing/trading_parties/models.py +110 -0
- {libredte_lib_sdk-0.1.0 → libredte_lib_sdk-0.3.0}/libredte_lib_sdk/client.py +35 -2
- {libredte_lib_sdk-0.1.0 → libredte_lib_sdk-0.3.0}/libredte_lib_sdk/exceptions.py +17 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/human_resources/__init__.py +28 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/human_resources/integration/__init__.py +22 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/human_resources/integration/previred_provider.py +41 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/human_resources/payroll/__init__.py +25 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/human_resources/payroll/calculator.py +51 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/human_resources/payroll/renderer.py +50 -0
- {libredte_lib_sdk-0.1.0 → libredte_lib_sdk-0.3.0}/libredte_lib_sdk/sdk.py +13 -3
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/system/__init__.py +30 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/system/certificate/__init__.py +22 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/system/certificate/loader.py +38 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/system/repository/__init__.py +22 -0
- libredte_lib_sdk-0.3.0/libredte_lib_sdk/system/repository/catalog.py +130 -0
- {libredte_lib_sdk-0.1.0 → libredte_lib_sdk-0.3.0}/pyproject.toml +12 -5
- libredte_lib_sdk-0.3.0/tests/__init__.py +3 -0
- {libredte_lib_sdk-0.1.0 → libredte_lib_sdk-0.3.0}/tests/conftest.py +5 -1
- libredte_lib_sdk-0.3.0/tests/integration/__init__.py +3 -0
- {libredte_lib_sdk-0.1.0 → libredte_lib_sdk-0.3.0}/tests/integration/conftest.py +60 -4
- libredte_lib_sdk-0.3.0/tests/integration/test_book.py +109 -0
- {libredte_lib_sdk-0.1.0 → libredte_lib_sdk-0.3.0}/tests/integration/test_caf.py +4 -1
- libredte_lib_sdk-0.3.0/tests/integration/test_certificate_loader.py +74 -0
- libredte_lib_sdk-0.3.0/tests/integration/test_document_loader.py +30 -0
- {libredte_lib_sdk-0.1.0 → libredte_lib_sdk-0.3.0}/tests/integration/test_document_rendering.py +4 -1
- libredte_lib_sdk-0.3.0/tests/integration/test_document_validation.py +113 -0
- libredte_lib_sdk-0.3.0/tests/integration/test_examples.py +72 -0
- libredte_lib_sdk-0.3.0/tests/integration/test_exchange.py +112 -0
- libredte_lib_sdk-0.3.0/tests/integration/test_human_resources.py +107 -0
- libredte_lib_sdk-0.3.0/tests/integration/test_operation_not_found.py +34 -0
- libredte_lib_sdk-0.3.0/tests/integration/test_ownership_transfer.py +56 -0
- libredte_lib_sdk-0.3.0/tests/integration/test_repository.py +83 -0
- {libredte_lib_sdk-0.1.0 → libredte_lib_sdk-0.3.0}/tests/test_client.py +51 -3
- {libredte_lib_sdk-0.1.0 → libredte_lib_sdk-0.3.0}/tests/test_models.py +54 -37
- libredte_lib_sdk-0.3.0/tests/test_services.py +1649 -0
- libredte_lib_sdk-0.1.0/.gitignore +0 -15
- libredte_lib_sdk-0.1.0/CLAUDE.md +0 -482
- libredte_lib_sdk-0.1.0/COPYING +0 -661
- libredte_lib_sdk-0.1.0/PKG-INFO +0 -878
- libredte_lib_sdk-0.1.0/libredte_lib_sdk/__init__.py +0 -75
- libredte_lib_sdk-0.1.0/libredte_lib_sdk/billing/document/builder.py +0 -68
- libredte_lib_sdk-0.1.0/libredte_lib_sdk/billing/document/dispatcher.py +0 -49
- libredte_lib_sdk-0.1.0/libredte_lib_sdk/billing/document/models.py +0 -169
- libredte_lib_sdk-0.1.0/libredte_lib_sdk/billing/enums.py +0 -18
- libredte_lib_sdk-0.1.0/libredte_lib_sdk/billing/identifier/caf_loader.py +0 -31
- libredte_lib_sdk-0.1.0/libredte_lib_sdk/billing/integration/__init__.py +0 -17
- libredte_lib_sdk-0.1.0/libredte_lib_sdk/billing/integration/models.py +0 -46
- libredte_lib_sdk-0.1.0/libredte_lib_sdk/billing/integration/sii_dte.py +0 -83
- libredte_lib_sdk-0.1.0/libredte_lib_sdk/billing/trading_parties/mandatario_manager.py +0 -45
- libredte_lib_sdk-0.1.0/libredte_lib_sdk/billing/trading_parties/models.py +0 -38
- libredte_lib_sdk-0.1.0/tests/__init__.py +0 -0
- libredte_lib_sdk-0.1.0/tests/integration/__init__.py +0 -0
- libredte_lib_sdk-0.1.0/tests/test_services.py +0 -428
- {libredte_lib_sdk-0.1.0 → libredte_lib_sdk-0.3.0}/libredte_lib_sdk/py.typed +0 -0
|
@@ -17,7 +17,7 @@ jobs:
|
|
|
17
17
|
strategy:
|
|
18
18
|
matrix:
|
|
19
19
|
os: [ubuntu-latest]
|
|
20
|
-
python-version: ['3.14']
|
|
20
|
+
python-version: ['3.11', '3.12', '3.13', '3.14']
|
|
21
21
|
|
|
22
22
|
steps:
|
|
23
23
|
- name: Check out repository
|
|
@@ -42,6 +42,9 @@ jobs:
|
|
|
42
42
|
- name: Run Ruff (format)
|
|
43
43
|
run: ruff format --check .
|
|
44
44
|
|
|
45
|
+
- name: Run mypy
|
|
46
|
+
run: mypy
|
|
47
|
+
|
|
45
48
|
# No corre los tests `live` (marker `live`, excluidos por defecto vía
|
|
46
49
|
# `addopts` en pyproject.toml): golpean la API real de LibreDTE y/o
|
|
47
50
|
# un ambiente de desarrollo local, no algo apto para CI.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
name: Docs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
push:
|
|
6
|
+
branches:
|
|
7
|
+
- main
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
docs:
|
|
11
|
+
name: Docs
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
|
|
14
|
+
steps:
|
|
15
|
+
- name: Check out repository
|
|
16
|
+
uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- name: Set up Python
|
|
19
|
+
uses: actions/setup-python@v5
|
|
20
|
+
with:
|
|
21
|
+
python-version: '3.13'
|
|
22
|
+
|
|
23
|
+
- name: Install dependencies
|
|
24
|
+
run: |
|
|
25
|
+
python -m pip install --upgrade pip
|
|
26
|
+
pip install -e '.[docs]'
|
|
27
|
+
|
|
28
|
+
- name: Generate API reference
|
|
29
|
+
run: sphinx-apidoc -o docs/ libredte_lib_sdk --force --separate
|
|
30
|
+
|
|
31
|
+
- name: Build documentation
|
|
32
|
+
run: sphinx-build -b html docs/ docs/_build/html
|
|
33
|
+
|
|
34
|
+
- name: Create CNAME file
|
|
35
|
+
run: echo "lib-sdk-python.docs.libredte.cl" > docs/_build/html/CNAME
|
|
36
|
+
|
|
37
|
+
- name: Deploy to GitHub Pages
|
|
38
|
+
if: success()
|
|
39
|
+
uses: peaceiris/actions-gh-pages@v4
|
|
40
|
+
with:
|
|
41
|
+
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
42
|
+
publish_dir: ./docs/_build/html
|
|
43
|
+
publish_branch: gh-pages
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Python.
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.venv/
|
|
6
|
+
venv/
|
|
7
|
+
.pytest_cache/
|
|
8
|
+
.ruff_cache/
|
|
9
|
+
dist/
|
|
10
|
+
build/
|
|
11
|
+
.coverage
|
|
12
|
+
var/
|
|
13
|
+
# Referencia de API generada por `sphinx-apidoc` (ver `make docs` /
|
|
14
|
+
# `build.jobs.pre_build` en `.readthedocs.yaml`) — no se commitea, se
|
|
15
|
+
# regenera en cada build a partir de los docstrings.
|
|
16
|
+
docs/_build/
|
|
17
|
+
docs/libredte_lib_sdk*.rst
|
|
18
|
+
docs/modules.rst
|
|
19
|
+
|
|
20
|
+
# Archivos específicos del sistema operativo.
|
|
21
|
+
.DS_Store
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# .readthedocs.yaml
|
|
2
|
+
# Read the Docs configuration file
|
|
3
|
+
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
|
4
|
+
|
|
5
|
+
version: 2
|
|
6
|
+
|
|
7
|
+
build:
|
|
8
|
+
os: ubuntu-24.04
|
|
9
|
+
tools:
|
|
10
|
+
python: "3.13"
|
|
11
|
+
jobs:
|
|
12
|
+
# La referencia de API (docs/libredte_lib_sdk*.rst, docs/modules.rst)
|
|
13
|
+
# no se commitea: se regenera acá a partir de los docstrings, igual
|
|
14
|
+
# que hace `make docs` en local.
|
|
15
|
+
pre_build:
|
|
16
|
+
- sphinx-apidoc -o docs/ libredte_lib_sdk --force --separate
|
|
17
|
+
|
|
18
|
+
sphinx:
|
|
19
|
+
configuration: docs/conf.py
|
|
20
|
+
|
|
21
|
+
python:
|
|
22
|
+
install:
|
|
23
|
+
- method: pip
|
|
24
|
+
path: .
|
|
25
|
+
extra_requirements:
|
|
26
|
+
- docs
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# `libredte_lib_sdk` — pendientes
|
|
2
|
+
|
|
3
|
+
## Pendiente
|
|
4
|
+
|
|
5
|
+
- **Tests en vivo de `integration.sii_dte`/`sii_rcv`/`sii_rtc`** (10
|
|
6
|
+
operaciones): tienen test unitario (mockeado), pero ninguno en
|
|
7
|
+
`live`. A diferencia del resto de la suite `live` (que usa
|
|
8
|
+
`fake_certificate`, autofirmado), estas operaciones hablan con el SII
|
|
9
|
+
real y necesitan un certificado real vigente — no hay fixture para
|
|
10
|
+
eso hoy, y committear uno no correspondería. Falta decidir el
|
|
11
|
+
mecanismo (ej. certificado real vía variable de entorno, `skip` si
|
|
12
|
+
no está disponible) antes de poder escribirlos.
|
|
13
|
+
- **DTO `Liquidacion` sin construir.** `human_resources.payroll
|
|
14
|
+
.calculator::calculate()` recibe `empleado`/`contrato`/`contexto`
|
|
15
|
+
como `dict` (correcto — son entradas) pero **devuelve** la
|
|
16
|
+
liquidación también como `dict`, sin tipar; al ser una respuesta,
|
|
17
|
+
debería tipar como un DTO real (reusable también como entrada de
|
|
18
|
+
`renderer::render()`, que hoy acepta el mismo `dict` tal cual, igual
|
|
19
|
+
que `Certificate`). Pendiente por el tamaño de la entidad real en
|
|
20
|
+
`libredte-lib-pro` (`Liquidacion`, con `Empleado`/`Contrato`/
|
|
21
|
+
`LiquidacionContexto` anidados; `Empleado` por sí solo tiene ~26
|
|
22
|
+
campos con varios enums y objetos anidados — `Contacto`,
|
|
23
|
+
`CuentaBancaria`, `CargaFamiliar`).
|
|
24
|
+
- **`exchange.receiver`/`exchange.sender`** (framework genérico de
|
|
25
|
+
intercambio de documentos comerciales, tipo Peppol/UBL, no solo DTE)
|
|
26
|
+
queda fuera del SDK — se agrega cuando una app consumidora lo
|
|
27
|
+
necesite de verdad.
|
|
28
|
+
- **Docs (Sphinx) armadas pero sin publicar.** `.readthedocs.yaml` +
|
|
29
|
+
`docs/` generan la documentación (`make docs`), y
|
|
30
|
+
`.github/workflows/docs.yml` ya publica a GitHub Pages
|
|
31
|
+
(`gh-pages`) con CNAME `lib-sdk-python.docs.libredte.cl` en cada
|
|
32
|
+
push a `main`. Faltan 2 pasos externos, ninguno hecho todavía: (1)
|
|
33
|
+
conectar el repo en readthedocs.org (sin eso no hay build ahí ni URL
|
|
34
|
+
en `readthedocs.io`); (2) apuntar el DNS de
|
|
35
|
+
`lib-sdk-python.docs.libredte.cl` a GitHub Pages y habilitar el
|
|
36
|
+
origen `gh-pages` en la configuración de Pages del repo (sin eso el
|
|
37
|
+
workflow corre pero el dominio no sirve nada).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (C) 2026 LibreDTE <https://www.libredte.cl>
|
|
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.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
.PHONY: install-dev lint format format-check test test-live check build upload clean
|
|
1
|
+
.PHONY: install-dev lint format format-check typecheck test test-live check docs build upload clean
|
|
2
2
|
|
|
3
3
|
VENV = .venv
|
|
4
4
|
VENV_READY = $(VENV)/.installed
|
|
@@ -20,6 +20,9 @@ format: $(VENV_READY)
|
|
|
20
20
|
format-check: $(VENV_READY)
|
|
21
21
|
$(VENV)/bin/ruff format --check .
|
|
22
22
|
|
|
23
|
+
typecheck: $(VENV_READY)
|
|
24
|
+
$(VENV)/bin/mypy
|
|
25
|
+
|
|
23
26
|
test: $(VENV_READY)
|
|
24
27
|
$(VENV)/bin/pytest -v
|
|
25
28
|
|
|
@@ -29,7 +32,12 @@ test: $(VENV_READY)
|
|
|
29
32
|
test-live: $(VENV_READY)
|
|
30
33
|
$(VENV)/bin/pytest -v -m live
|
|
31
34
|
|
|
32
|
-
check: lint format-check test
|
|
35
|
+
check: lint format-check typecheck test
|
|
36
|
+
|
|
37
|
+
docs: $(VENV_READY)
|
|
38
|
+
$(VENV)/bin/pip install -e '.[docs]'
|
|
39
|
+
$(VENV)/bin/sphinx-apidoc -o docs libredte_lib_sdk --force --separate
|
|
40
|
+
$(VENV)/bin/sphinx-build -b html docs docs/_build/html
|
|
33
41
|
|
|
34
42
|
build: $(VENV_READY)
|
|
35
43
|
$(VENV)/bin/python -m build
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: libredte-lib-sdk
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: SDK Python para la API de LibreDTE Lib (facturacion electronica de Chile).
|
|
5
|
+
Project-URL: Homepage, https://www.libredte.cl
|
|
6
|
+
Project-URL: Source, https://github.com/libredte/libredte-lib-sdk-python
|
|
7
|
+
Author: LibreDTE
|
|
8
|
+
License: MIT License
|
|
9
|
+
|
|
10
|
+
Copyright (C) 2026 LibreDTE <https://www.libredte.cl>
|
|
11
|
+
|
|
12
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
13
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
14
|
+
in the Software without restriction, including without limitation the rights
|
|
15
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
16
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
17
|
+
furnished to do so, subject to the following conditions:
|
|
18
|
+
|
|
19
|
+
The above copyright notice and this permission notice shall be included in all
|
|
20
|
+
copies or substantial portions of the Software.
|
|
21
|
+
|
|
22
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
23
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
24
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
25
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
26
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
27
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
28
|
+
SOFTWARE.
|
|
29
|
+
License-File: LICENSE
|
|
30
|
+
Requires-Python: >=3.11
|
|
31
|
+
Requires-Dist: httpx>=0.27
|
|
32
|
+
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: build; extra == 'dev'
|
|
34
|
+
Requires-Dist: mypy; extra == 'dev'
|
|
35
|
+
Requires-Dist: pytest; extra == 'dev'
|
|
36
|
+
Requires-Dist: pytest-cov; extra == 'dev'
|
|
37
|
+
Requires-Dist: respx; extra == 'dev'
|
|
38
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
39
|
+
Requires-Dist: twine; extra == 'dev'
|
|
40
|
+
Provides-Extra: docs
|
|
41
|
+
Requires-Dist: sphinx; extra == 'docs'
|
|
42
|
+
Requires-Dist: sphinx-rtd-theme; extra == 'docs'
|
|
43
|
+
Description-Content-Type: text/x-rst
|
|
44
|
+
|
|
45
|
+
LibreDTE: SDK Python para la API de LibreDTE Lib
|
|
46
|
+
================================================
|
|
47
|
+
|
|
48
|
+
SDK Python (``libredte_lib_sdk``) que orquesta la API de LibreDTE Lib
|
|
49
|
+
(``https://core.libredte.cl/api`` por defecto) para cubrir el ciclo de
|
|
50
|
+
emisión de un DTE: borrador, documento timbrado y firmado,
|
|
51
|
+
envío al SII, consulta de estado por Track ID, y generación de HTML/PDF
|
|
52
|
+
— más carga y validación de CAF real, y generación de CAF y certificado
|
|
53
|
+
ficticios para poder probar todo lo anterior sin credenciales reales.
|
|
54
|
+
|
|
55
|
+
Pensado como base de una app de facturación (ej. Django): este SDK
|
|
56
|
+
concentra la lógica de negocio/orquestación de DTE, para que la app web
|
|
57
|
+
sea solo vista, autenticación y persistencia.
|
|
58
|
+
|
|
59
|
+
El paquete Python espeja la organización de la propia API
|
|
60
|
+
(``package.component.worker::operation``): ``sdk.billing.<component>
|
|
61
|
+
.<worker>`` para negocio DTE, ``sdk.system.<component>.<worker>`` para
|
|
62
|
+
infraestructura de la biblioteca (catálogos reales, carga de certificados
|
|
63
|
+
— ver "Recursos de `system`" más abajo).
|
|
64
|
+
|
|
65
|
+
Instalación
|
|
66
|
+
-----------
|
|
67
|
+
|
|
68
|
+
.. code-block:: bash
|
|
69
|
+
|
|
70
|
+
pip install libredte-lib-sdk
|
|
71
|
+
|
|
72
|
+
Uso
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
.. code-block:: python
|
|
76
|
+
|
|
77
|
+
from libredte_lib_sdk import LibreDTE
|
|
78
|
+
from libredte_lib_sdk.billing.trading_parties import Mandatario
|
|
79
|
+
|
|
80
|
+
sdk = LibreDTE() # base_url y api_token también vía env vars, ver abajo
|
|
81
|
+
b = sdk.billing
|
|
82
|
+
|
|
83
|
+
input_data = {
|
|
84
|
+
'Encabezado': {
|
|
85
|
+
'IdDoc': {
|
|
86
|
+
'TipoDTE': 33,
|
|
87
|
+
'Folio': 1
|
|
88
|
+
},
|
|
89
|
+
'Emisor': {
|
|
90
|
+
'RUTEmisor': '76192083-9',
|
|
91
|
+
'RznSoc': 'SASCO SpA',
|
|
92
|
+
'GiroEmis': 'Servicios',
|
|
93
|
+
'DirOrigen': 'Santiago',
|
|
94
|
+
'CmnaOrigen': 'Santiago',
|
|
95
|
+
},
|
|
96
|
+
'Receptor': {
|
|
97
|
+
'RUTRecep': '12345678-5',
|
|
98
|
+
'RznSocRecep': 'Cliente de prueba',
|
|
99
|
+
'GiroRecep': 'Giro',
|
|
100
|
+
'DirRecep': 'Santiago',
|
|
101
|
+
'CmnaRecep': 'Santiago',
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
'Detalle': [
|
|
105
|
+
{
|
|
106
|
+
'NmbItem': 'Producto A',
|
|
107
|
+
'QtyItem': 1,
|
|
108
|
+
'PrcItem': 1000
|
|
109
|
+
}
|
|
110
|
+
],
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
# CAF y certificado ficticios, para pruebas/desarrollo:
|
|
114
|
+
caf = b.identifier.caf_faker.create(
|
|
115
|
+
{'rut': '76192083-9', 'razon_social': 'SASCO SpA'},
|
|
116
|
+
codigo_documento=33, folio_desde=1, folio_hasta=100,
|
|
117
|
+
)
|
|
118
|
+
certificate = b.trading_parties.mandatario_manager.create_fake_certificate(
|
|
119
|
+
Mandatario(rut='76192083-9', nombre='SASCO SpA', email='sasco@example.com'),
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
# En producción: cargar y validar el CAF real que el SII le entregó
|
|
123
|
+
# al emisor, en vez del CAF ficticio de arriba.
|
|
124
|
+
# caf = b.identifier.caf_loader.load(xml_base64_del_caf_subido)
|
|
125
|
+
# b.identifier.caf_validator.validate(caf.xml_base64)
|
|
126
|
+
|
|
127
|
+
# 1. Borrador.
|
|
128
|
+
borrador = b.document.builder.build_draft(input_data)
|
|
129
|
+
|
|
130
|
+
# 2. Documento real, timbrado y firmado.
|
|
131
|
+
documento = b.document.builder.build_signed(
|
|
132
|
+
input_data, caf_xml=caf.xml_base64, certificate=certificate,
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
# 3. Envío al SII (arma el sobre EnvioDTE y luego lo envía).
|
|
136
|
+
emisor = {
|
|
137
|
+
'rut': '76192083-9',
|
|
138
|
+
'razon_social': 'SASCO SpA',
|
|
139
|
+
'autorizacion_dte': {
|
|
140
|
+
'fecha_resolucion': '2014-08-22', 'numero_resolucion': 80,
|
|
141
|
+
},
|
|
142
|
+
}
|
|
143
|
+
sobre = b.document.dispatcher.create(
|
|
144
|
+
documento.xml_base64, certificate=certificate, emisor=emisor,
|
|
145
|
+
)
|
|
146
|
+
envio = b.integration.sii_dte.send(
|
|
147
|
+
sobre.xml_base64, certificate=certificate, company_rut='76192083-9',
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
# 4. Estado del envío, por Track ID.
|
|
151
|
+
estado = b.integration.sii_dte.check_status(
|
|
152
|
+
envio.track_id, certificate=certificate, company_rut='76192083-9',
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
# 5. HTML o PDF — misma forma de respuesta para ambos.
|
|
156
|
+
html = b.document.renderer.render(documento.xml_base64, format='html')
|
|
157
|
+
pdf = b.document.renderer.render(documento.xml_base64, format='pdf')
|
|
158
|
+
pdf_bytes = pdf.first.content_bytes
|
|
159
|
+
|
|
160
|
+
# Varias copias/presentaciones en una sola llamada (ej. cedible +
|
|
161
|
+
# tributaria):
|
|
162
|
+
copias = b.document.renderer.render(
|
|
163
|
+
documento.xml_base64,
|
|
164
|
+
format='pdf',
|
|
165
|
+
renderings={'tributaria': 1, 'cedible': 1},
|
|
166
|
+
)
|
|
167
|
+
cedible_bytes = copias.by_label('cedible')[0].content_bytes
|
|
168
|
+
|
|
169
|
+
Cada componente (``document``, ``identifier``, ``trading_parties``,
|
|
170
|
+
``integration``) agrupa servicios independientes, uno por *worker* de la
|
|
171
|
+
API: cada método hace exactamente una llamada HTTP, sin encadenar red por
|
|
172
|
+
detrás. Encadenar los pasos (ej. armar el documento, el sobre, y
|
|
173
|
+
enviarlo) es responsabilidad de quien use el SDK.
|
|
174
|
+
|
|
175
|
+
Configuración
|
|
176
|
+
-------------
|
|
177
|
+
|
|
178
|
+
Base URL
|
|
179
|
+
~~~~~~~~
|
|
180
|
+
|
|
181
|
+
Por defecto el SDK apunta a ``https://core.libredte.cl/api``. Para usar
|
|
182
|
+
otra API (ej. ``https://pro.libredte.cl/api``, o un ambiente propio),
|
|
183
|
+
pasar ``base_url`` al construir ``LibreDTE`` o setear la variable de
|
|
184
|
+
entorno ``LIBREDTE_LIB_SDK_BASE_URL``:
|
|
185
|
+
|
|
186
|
+
.. code-block:: python
|
|
187
|
+
|
|
188
|
+
sdk = LibreDTE(base_url='https://pro.libredte.cl/api')
|
|
189
|
+
|
|
190
|
+
.. code-block:: bash
|
|
191
|
+
|
|
192
|
+
export LIBREDTE_LIB_SDK_BASE_URL=https://pro.libredte.cl/api
|
|
193
|
+
|
|
194
|
+
``core.libredte.cl`` y ``pro.libredte.cl`` exponen el mismo contrato con
|
|
195
|
+
límites de solicitudes distintos; ambos aceptan la variante ``LibreDTE
|
|
196
|
+
(base_url=..., ...)`` con el resto de los parámetros de configuración
|
|
197
|
+
(``api_token``, ``timeout``, ``http_client``).
|
|
198
|
+
|
|
199
|
+
Autenticación
|
|
200
|
+
~~~~~~~~~~~~~
|
|
201
|
+
|
|
202
|
+
``LibreDTE(api_token=...)`` o la variable de entorno
|
|
203
|
+
``LIBREDTE_LIB_SDK_TOKEN`` — si está presente, se manda como header
|
|
204
|
+
``Authorization: Bearer <token>``.
|
|
205
|
+
|
|
206
|
+
Recursos de ``system``
|
|
207
|
+
-----------------------
|
|
208
|
+
|
|
209
|
+
Además de ``billing`` (negocio DTE), el SDK expone ``system``:
|
|
210
|
+
infraestructura de la biblioteca que una app consumidora
|
|
211
|
+
necesita para poblar sus propios datos, no operaciones de facturación.
|
|
212
|
+
|
|
213
|
+
.. code-block:: python
|
|
214
|
+
|
|
215
|
+
s = sdk.system
|
|
216
|
+
|
|
217
|
+
# Ejemplos de documentos reales (los mismos casos de prueba,
|
|
218
|
+
# validados, de libredte-lib-core) — útiles para poblar datos de
|
|
219
|
+
# demostración con variedad real en vez de inventada a mano.
|
|
220
|
+
ejemplos = b.document.examples.list() # [ExampleSummary(id=..., category=..., case=...), ...]
|
|
221
|
+
ejemplo = b.document.examples.get(ejemplos[0].id)
|
|
222
|
+
documento = b.document.builder.build_signed(
|
|
223
|
+
ejemplo.input_data, caf_xml=caf.xml_base64, certificate=certificate,
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
# Catálogos/repositorios reales (comunas, tipos de documento, etc.)
|
|
227
|
+
# — el esquema de cada elemento depende del repositorio pedido, no
|
|
228
|
+
# hay un DTO fijo: se devuelve el dict/list tal cual la API.
|
|
229
|
+
repositorios = s.repository.catalog.list() # FQCN de cada repositorio disponible
|
|
230
|
+
tipos_dte = s.repository.catalog.find_by(
|
|
231
|
+
'libredte\\lib\\Core\\Package\\Billing\\Component\\Document'
|
|
232
|
+
'\\Contract\\TipoDocumentoInterface',
|
|
233
|
+
criteria={'codigo': [33, 39]}, # coincidencia con cualquiera de estos códigos
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
# Cargar un certificado real (.p12/.pfx) sin desempaquetarlo
|
|
237
|
+
# localmente: la API entrega certificado (PEM) + RUT/nombre/correo
|
|
238
|
+
# ya extraídos en una sola llamada — mismo `Certificate` que usan
|
|
239
|
+
# build_signed()/dispatcher.create(), ya con todos los datos.
|
|
240
|
+
certificate = s.certificate.loader.load(datos_del_archivo_pfx, 'contraseña')
|
|
241
|
+
print(certificate.rut, certificate.nombre, certificate.email)
|
|
242
|
+
|
|
243
|
+
Errores
|
|
244
|
+
-------
|
|
245
|
+
|
|
246
|
+
Cualquier error de la API (validación, regla de negocio, error interno)
|
|
247
|
+
levanta ``libredte_lib_sdk.LibreDteApiError``, con ``.status_code``,
|
|
248
|
+
``.detail`` y ``.php_class`` (la clase real de la excepción PHP detrás,
|
|
249
|
+
si la API la informó — ej. ``DocumentException``, o una excepción de
|
|
250
|
+
autenticación del SII). Un ``429`` de la API levanta
|
|
251
|
+
``LibreDteRateLimitError`` (subclase de lo anterior), con
|
|
252
|
+
``.retry_after``/``.limit``/``.remaining``. Un problema de red levanta
|
|
253
|
+
``libredte_lib_sdk.LibreDteConnectionError``.
|
|
254
|
+
|
|
255
|
+
Desarrollo
|
|
256
|
+
----------
|
|
257
|
+
|
|
258
|
+
.. code-block:: bash
|
|
259
|
+
|
|
260
|
+
make install-dev
|
|
261
|
+
make check # ruff + tests unitarios (offline, sin red)
|
|
262
|
+
make test-live # tests de integración reales contra la API
|
|
263
|
+
|
|
264
|
+
Los tests unitarios no hacen red real: mockean la API con ``respx``. Los
|
|
265
|
+
de ``tests/integration/`` sí (marker ``live``), y están excluidos por
|
|
266
|
+
defecto de ``pytest``/``make test``/``make check``.
|
|
267
|
+
|
|
268
|
+
Términos y condiciones de uso
|
|
269
|
+
------------------------------
|
|
270
|
+
|
|
271
|
+
Este proyecto está licenciado bajo la Licencia MIT. Ver
|
|
272
|
+
`LICENSE <LICENSE>`_.
|
|
@@ -2,8 +2,8 @@ LibreDTE: SDK Python para la API de LibreDTE Lib
|
|
|
2
2
|
================================================
|
|
3
3
|
|
|
4
4
|
SDK Python (``libredte_lib_sdk``) que orquesta la API de LibreDTE Lib
|
|
5
|
-
(``https://core.libredte.cl/api`` por defecto) para cubrir el ciclo
|
|
6
|
-
|
|
5
|
+
(``https://core.libredte.cl/api`` por defecto) para cubrir el ciclo de
|
|
6
|
+
emisión de un DTE: borrador, documento timbrado y firmado,
|
|
7
7
|
envío al SII, consulta de estado por Track ID, y generación de HTML/PDF
|
|
8
8
|
— más carga y validación de CAF real, y generación de CAF y certificado
|
|
9
9
|
ficticios para poder probar todo lo anterior sin credenciales reales.
|
|
@@ -13,8 +13,10 @@ concentra la lógica de negocio/orquestación de DTE, para que la app web
|
|
|
13
13
|
sea solo vista, autenticación y persistencia.
|
|
14
14
|
|
|
15
15
|
El paquete Python espeja la organización de la propia API
|
|
16
|
-
(``
|
|
17
|
-
.<worker
|
|
16
|
+
(``package.component.worker::operation``): ``sdk.billing.<component>
|
|
17
|
+
.<worker>`` para negocio DTE, ``sdk.system.<component>.<worker>`` para
|
|
18
|
+
infraestructura de la biblioteca (catálogos reales, carga de certificados
|
|
19
|
+
— ver "Recursos de `system`" más abajo).
|
|
18
20
|
|
|
19
21
|
Instalación
|
|
20
22
|
-----------
|
|
@@ -28,14 +30,18 @@ Uso
|
|
|
28
30
|
|
|
29
31
|
.. code-block:: python
|
|
30
32
|
|
|
31
|
-
from libredte_lib_sdk import
|
|
33
|
+
from libredte_lib_sdk import LibreDTE
|
|
34
|
+
from libredte_lib_sdk.billing.trading_parties import Mandatario
|
|
32
35
|
|
|
33
36
|
sdk = LibreDTE() # base_url y api_token también vía env vars, ver abajo
|
|
34
37
|
b = sdk.billing
|
|
35
38
|
|
|
36
|
-
|
|
39
|
+
input_data = {
|
|
37
40
|
'Encabezado': {
|
|
38
|
-
'IdDoc': {
|
|
41
|
+
'IdDoc': {
|
|
42
|
+
'TipoDTE': 33,
|
|
43
|
+
'Folio': 1
|
|
44
|
+
},
|
|
39
45
|
'Emisor': {
|
|
40
46
|
'RUTEmisor': '76192083-9',
|
|
41
47
|
'RznSoc': 'SASCO SpA',
|
|
@@ -51,7 +57,13 @@ Uso
|
|
|
51
57
|
'CmnaRecep': 'Santiago',
|
|
52
58
|
},
|
|
53
59
|
},
|
|
54
|
-
'Detalle': [
|
|
60
|
+
'Detalle': [
|
|
61
|
+
{
|
|
62
|
+
'NmbItem': 'Producto A',
|
|
63
|
+
'QtyItem': 1,
|
|
64
|
+
'PrcItem': 1000
|
|
65
|
+
}
|
|
66
|
+
],
|
|
55
67
|
}
|
|
56
68
|
|
|
57
69
|
# CAF y certificado ficticios, para pruebas/desarrollo:
|
|
@@ -60,7 +72,7 @@ Uso
|
|
|
60
72
|
codigo_documento=33, folio_desde=1, folio_hasta=100,
|
|
61
73
|
)
|
|
62
74
|
certificate = b.trading_parties.mandatario_manager.create_fake_certificate(
|
|
63
|
-
|
|
75
|
+
Mandatario(rut='76192083-9', nombre='SASCO SpA', email='sasco@example.com'),
|
|
64
76
|
)
|
|
65
77
|
|
|
66
78
|
# En producción: cargar y validar el CAF real que el SII le entregó
|
|
@@ -69,21 +81,21 @@ Uso
|
|
|
69
81
|
# b.identifier.caf_validator.validate(caf.xml_base64)
|
|
70
82
|
|
|
71
83
|
# 1. Borrador.
|
|
72
|
-
borrador = b.document.builder.build_draft(
|
|
84
|
+
borrador = b.document.builder.build_draft(input_data)
|
|
73
85
|
|
|
74
86
|
# 2. Documento real, timbrado y firmado.
|
|
75
87
|
documento = b.document.builder.build_signed(
|
|
76
|
-
|
|
88
|
+
input_data, caf_xml=caf.xml_base64, certificate=certificate,
|
|
77
89
|
)
|
|
78
90
|
|
|
79
91
|
# 3. Envío al SII (arma el sobre EnvioDTE y luego lo envía).
|
|
80
|
-
emisor =
|
|
81
|
-
rut
|
|
82
|
-
razon_social
|
|
83
|
-
autorizacion_dte
|
|
84
|
-
fecha_resolucion
|
|
85
|
-
|
|
86
|
-
|
|
92
|
+
emisor = {
|
|
93
|
+
'rut': '76192083-9',
|
|
94
|
+
'razon_social': 'SASCO SpA',
|
|
95
|
+
'autorizacion_dte': {
|
|
96
|
+
'fecha_resolucion': '2014-08-22', 'numero_resolucion': 80,
|
|
97
|
+
},
|
|
98
|
+
}
|
|
87
99
|
sobre = b.document.dispatcher.create(
|
|
88
100
|
documento.xml_base64, certificate=certificate, emisor=emisor,
|
|
89
101
|
)
|
|
@@ -147,22 +159,42 @@ Autenticación
|
|
|
147
159
|
``LIBREDTE_LIB_SDK_TOKEN`` — si está presente, se manda como header
|
|
148
160
|
``Authorization: Bearer <token>``.
|
|
149
161
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
``
|
|
154
|
-
de
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
162
|
+
Recursos de ``system``
|
|
163
|
+
-----------------------
|
|
164
|
+
|
|
165
|
+
Además de ``billing`` (negocio DTE), el SDK expone ``system``:
|
|
166
|
+
infraestructura de la biblioteca que una app consumidora
|
|
167
|
+
necesita para poblar sus propios datos, no operaciones de facturación.
|
|
168
|
+
|
|
169
|
+
.. code-block:: python
|
|
170
|
+
|
|
171
|
+
s = sdk.system
|
|
172
|
+
|
|
173
|
+
# Ejemplos de documentos reales (los mismos casos de prueba,
|
|
174
|
+
# validados, de libredte-lib-core) — útiles para poblar datos de
|
|
175
|
+
# demostración con variedad real en vez de inventada a mano.
|
|
176
|
+
ejemplos = b.document.examples.list() # [ExampleSummary(id=..., category=..., case=...), ...]
|
|
177
|
+
ejemplo = b.document.examples.get(ejemplos[0].id)
|
|
178
|
+
documento = b.document.builder.build_signed(
|
|
179
|
+
ejemplo.input_data, caf_xml=caf.xml_base64, certificate=certificate,
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
# Catálogos/repositorios reales (comunas, tipos de documento, etc.)
|
|
183
|
+
# — el esquema de cada elemento depende del repositorio pedido, no
|
|
184
|
+
# hay un DTO fijo: se devuelve el dict/list tal cual la API.
|
|
185
|
+
repositorios = s.repository.catalog.list() # FQCN de cada repositorio disponible
|
|
186
|
+
tipos_dte = s.repository.catalog.find_by(
|
|
187
|
+
'libredte\\lib\\Core\\Package\\Billing\\Component\\Document'
|
|
188
|
+
'\\Contract\\TipoDocumentoInterface',
|
|
189
|
+
criteria={'codigo': [33, 39]}, # coincidencia con cualquiera de estos códigos
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
# Cargar un certificado real (.p12/.pfx) sin desempaquetarlo
|
|
193
|
+
# localmente: la API entrega certificado (PEM) + RUT/nombre/correo
|
|
194
|
+
# ya extraídos en una sola llamada — mismo `Certificate` que usan
|
|
195
|
+
# build_signed()/dispatcher.create(), ya con todos los datos.
|
|
196
|
+
certificate = s.certificate.loader.load(datos_del_archivo_pfx, 'contraseña')
|
|
197
|
+
print(certificate.rut, certificate.nombre, certificate.email)
|
|
166
198
|
|
|
167
199
|
Errores
|
|
168
200
|
-------
|
|
@@ -192,7 +224,5 @@ defecto de ``pytest``/``make test``/``make check``.
|
|
|
192
224
|
Términos y condiciones de uso
|
|
193
225
|
------------------------------
|
|
194
226
|
|
|
195
|
-
Este proyecto
|
|
196
|
-
|
|
197
|
-
versión 3 o (a elección) cualquier versión posterior. Ver
|
|
198
|
-
`COPYING <COPYING>`_.
|
|
227
|
+
Este proyecto está licenciado bajo la Licencia MIT. Ver
|
|
228
|
+
`LICENSE <LICENSE>`_.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Minimal makefile for Sphinx documentation
|
|
2
|
+
#
|
|
3
|
+
|
|
4
|
+
# You can set these variables from the command line, and also
|
|
5
|
+
# from the environment for the first two.
|
|
6
|
+
SPHINXOPTS ?=
|
|
7
|
+
SPHINXBUILD ?= sphinx-build
|
|
8
|
+
SOURCEDIR = .
|
|
9
|
+
BUILDDIR = _build
|
|
10
|
+
|
|
11
|
+
# Put it first so that "make" without argument is like "make help".
|
|
12
|
+
help:
|
|
13
|
+
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
14
|
+
|
|
15
|
+
.PHONY: help Makefile
|
|
16
|
+
|
|
17
|
+
# Catch-all target: route all unknown targets to Sphinx using the new
|
|
18
|
+
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
|
19
|
+
%: Makefile
|
|
20
|
+
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|