Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Contribuir

## Entorno

El proyecto se gestiona con [uv](https://docs.astral.sh/uv/getting-started/installation/)
0.13.0. `.python-version` fija Python 3.15.0 para desarrollo; el paquete sigue
siendo compatible con Python 3.11–3.15. uv descarga el intérprete cuando hace falta.

Para instalar el entorno, comprobar el código y ejecutar las pruebas:

```bash
uv sync --locked
uv run --locked ruff check .
uv run --locked ruff format --check .
uv run --locked python -m unittest discover -s tests -v
```

`pyproject.toml` declara las dependencias y `uv.lock` fija las versiones del
entorno de desarrollo; ambos archivos se versionan. `--locked` exige que el lock
coincida con el proyecto, sin actualizarlo durante las comprobaciones.

El grupo `dev` contiene las herramientas de validación; no forman parte de las
dependencias de ejecución. Quienes instalan el paquete con pip resuelven el
rango `httpx>=0.28.1,<1` sin usar nuestro lockfile.

## Lint y formato

Ruff comprueba y formatea todo el código Python, incluidas las pruebas. La
configuración usa Python 3.11 como mínimo y activa `E4`, `E7`, `E9` y `F` para
errores básicos, `I` para ordenar imports, `UP` para sintaxis compatible con ese
mínimo y `B` para errores comunes. El formato usa los valores predeterminados de
Ruff, sin excluir reglas ni archivos.

Para aplicar correcciones automáticas y formato:

```bash
uv run --locked ruff check --fix .
uv run --locked ruff format .
```

Revisa los cambios y ejecuta las comprobaciones y pruebas antes de enviarlos.

## Pruebas

Las pruebas comprueban el contrato HTTP de las funciones y los clientes. Un
servidor local permite verificar la reutilización y el cierre de conexiones,
además de la concurrencia asíncrona. No consultan la API de producción.

## Dependencias

Para añadir o quitar dependencias usa `uv add` y `uv remove`; para herramientas,
añade `--dev`. Para actualizar HTTPX dentro del rango permitido:

```bash
uv lock --upgrade-package httpx
uv sync --locked
uv run --locked python -m unittest discover -s tests -v
```

Revisa y versiona los cambios de `pyproject.toml` y `uv.lock` que correspondan.

## Construir el paquete

```bash
uv build
uv run --locked twine check dist/*
```

`uv build` usa el backend `setuptools` fijado en `[build-system]`, en un entorno
de construcción aislado. Sus dependencias se resuelven por separado del lockfile.

Para comprobar que el wheel instala sus propias dependencias, usa otro entorno:

```bash
uv venv .venv-wheel
uv pip install --python .venv-wheel/bin/python dist/*.whl
uv pip check --python .venv-wheel/bin/python
.venv-wheel/bin/python -c 'import tu_ruc_python_client'
.venv-wheel/bin/python -m unittest discover -s tests -v
```

## Publicación

CI exige lint y formato correctos, construye el paquete una vez y prueba ese
wheel en entornos limpios con Python 3.11–3.15.

Para publicar, crea un tag `0.1.0` o `v0.1.0` que coincida con la versión del
paquete. Solo se publica en PyPI si toda la matriz pasa. El workflow usa
`uv publish` con los mismos artefactos comprobados y el secreto `PYPI_TOKEN`,
expuesto al comando como `UV_PUBLISH_TOKEN`.

Registra los cambios de cada versión en [CHANGELOG.md](CHANGELOG.md).
176 changes: 58 additions & 118 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
# tu-ruc-python-client

![pipeline](https://github.com/ithdev/tu-ruc-python-client/blob/main/turuc.png?raw=true)
![Tu RUC y Python](https://github.com/ithdev/tu-ruc-python-client/blob/main/turuc.png?raw=true)

Cliente Python para consultar contribuyentes en la API de TuRuc Paraguay.
Incluye clientes síncrono y asíncrono con conexiones reutilizables mediante HTTPX.
Cliente Python para consultar contribuyentes en la API de
[TuRuc Paraguay](https://turuc.com.py/). Incluye un cliente síncrono y uno
asíncrono que reutilizan sus conexiones.

## Instalación

Requiere Python 3.11 o posterior. La versión 0.1.0 se prueba con CPython
3.11, 3.12, 3.13, 3.14 y 3.15. Python no tiene una versión LTS oficial;
seguimos las [versiones con soporte de Python](https://devguide.python.org/versions/).
Requiere Python 3.11 o posterior.

```bash
pip install tu_ruc_python_client
```

La instalación incluye `httpx>=0.28.1,<1` automáticamente. Requests deja de
ser una dependencia de ejecución del cliente.
La instalación incluye su única dependencia, [HTTPX](https://www.python-httpx.org/).

## Cliente síncrono

Expand All @@ -36,7 +34,7 @@ with TuRucClient() as client:
## Cliente asíncrono

Reutiliza la misma instancia dentro de un bucle de eventos. `async with`
cierra sus conexiones; `asyncio.gather` permite realizar consultas concurrentes.
cierra sus conexiones; `asyncio.gather` permite hacer consultas concurrentes.

```python
import asyncio
Expand All @@ -56,54 +54,49 @@ async def main():
asyncio.run(main())
```

Crea el cliente fuera del bucle que realiza consultas para conservar las
conexiones. Los ejemplos muestran cargas pequeñas; para procesar lotes grandes,
limita la concurrencia según la capacidad de la API.
Crea el cliente una sola vez, fuera del código que repite las consultas, para
conservar las conexiones. Para procesar lotes grandes, limita la concurrencia
según la capacidad de la API.

## Parámetros y respuestas

Ambos clientes exponen los mismos métodos:

| Método | Parámetros | Resultado |
|---|---|---|
| `get_contribuyente_by_search(search, page=0)` | Texto de 3–50 caracteres; página entera de 0–10 | Objeto con `contribuyentes` y `paginas` |
| `get_contribuyente_by_ruc(ruc)` | RUC o CI como texto, por ejemplo `5898204-3` | Objeto del contribuyente |
| Método | Parámetros | Resultado |
| --------------------------------------------- | ------------------------------------------------------ | ---------------------------------------- |
| `get_contribuyente_by_search(search, page=0)` | Texto de 3 a 50 caracteres; página entera de 0 a 10 | Objeto con `contribuyentes` y `paginas` |
| `get_contribuyente_by_ruc(ruc)` | RUC o CI como texto, por ejemplo `5898204-3` | Objeto del contribuyente |

Los métodos devuelven el campo `data` de la respuesta JSON. Conservan el
comportamiento previo: `data: null` se devuelve como `None`, incluso en una
respuesta HTTP 400. No convierten automáticamente los estados HTTP en excepciones.
Las búsquedas preservan caracteres como `&`, `+`, espacios y acentos.
Los métodos devuelven el campo `data` de la respuesta JSON de la API:

Los constructores aceptan argumentos opcionales por nombre:
- Si la API no devuelve datos, el resultado es `None`, también ante un error
HTTP como 400.
- Los estados HTTP de error no se convierten en excepciones.
- Puedes buscar textos con `&`, `+`, espacios y acentos; se envían tal cual.

### Configuración

Los constructores aceptan estos argumentos opcionales por nombre:

```python
with TuRucClient(base_url="https://turuc.com.py/", timeout=10.0) as client:
resultado = client.get_contribuyente_by_search("A&B ÑANDÚ + CIA")
```

`timeout` vale 10 segundos por defecto y se aplica a las fases de conexión,
lectura, escritura y espera de conexión disponible; no es un plazo total de la
consulta. `timeout=None` desactiva esos límites. Ambos clientes siguen
redirecciones. Si administras el ciclo de vida sin un bloque de contexto,
llama a `client.close()` o `await client.aclose()` al terminar.

## Migración desde las funciones anteriores

Las dos funciones siguen disponibles con sus parámetros y respuestas habituales:
- `timeout`: 10 segundos por defecto. Se aplica por separado a la conexión, la
lectura, la escritura y la espera de una conexión libre; no limita la duración
total de la consulta. `timeout=None` desactiva los límites.
- Ambos clientes siguen las redirecciones.

```python
from tu_ruc_python_client import get_contribuyente_by_ruc, get_contribuyente_by_search

print(get_contribuyente_by_search("juan perez", page=2))
print(get_contribuyente_by_ruc("5898204-3"))
```
Si no usas un bloque `with`, cierra el cliente al terminar con `client.close()`
o `await client.aclose()`.

Cada llamada abre y cierra su propio cliente HTTP; para reutilizar conexiones
entre consultas, migra a `TuRucClient` o `AsyncTuRucClient`. Las funciones
conservan la ausencia de timeout y el seguimiento de redirecciones previos.
## Errores

Los errores de transporte ahora pertenecen a HTTPX. Cambia las capturas de
`requests.exceptions.RequestException` por `httpx.RequestError`:
- **Parámetros inválidos:** los métodos lanzan `ValueError` o
`tu_ruc_python_client.exceptions.LengthError` antes de consultar la API.
- **Fallos de red y timeouts:** se propagan los errores de HTTPX
(`httpx.RequestError` y sus subclases).

```python
import httpx
Expand All @@ -119,93 +112,40 @@ except httpx.RequestError as exc:
print(f"No se pudo completar la consulta: {exc}")
```

Para certificados de confianza personalizados, HTTPX utiliza `SSL_CERT_FILE`
o `SSL_CERT_DIR`; revisa la configuración si antes usabas `REQUESTS_CA_BUNDLE`.
Consulta las [diferencias con Requests](https://www.python-httpx.org/compatibility/)
y las [variables de entorno de HTTPX](https://www.python-httpx.org/environment_variables/).

## Desarrollo y pruebas

El proyecto se gestiona con [uv](https://docs.astral.sh/uv/getting-started/installation/)
0.13.0. `.python-version` fija Python 3.15.0 para desarrollo; el paquete sigue
siendo compatible con Python 3.11–3.15. uv descarga el intérprete cuando hace falta.

Para instalar el entorno, comprobar el código y ejecutar las pruebas:

```bash
uv sync --locked
uv run --locked ruff check .
uv run --locked ruff format --check .
uv run --locked python -m unittest discover -s tests -v
```

`pyproject.toml` declara las dependencias y `uv.lock` fija las versiones del
entorno de desarrollo. Ambos archivos se versionan. `--locked` exige que el lock
coincida con el proyecto, sin actualizarlo durante las comprobaciones.
El grupo `dev` contiene las herramientas de validación del paquete; esas
herramientas no forman parte de las dependencias de ejecución del cliente.
Los consumidores pueden seguir instalando el SDK con pip y resolver el rango
`httpx>=0.28.1,<1` sin utilizar nuestro lockfile.

Ruff 0.17.0 comprueba y formatea todo el código Python, incluidas las pruebas.
La configuración usa Python 3.11 como mínimo y activa
`E4`, `E7`, `E9` y `F` para errores básicos, `I` para ordenar imports, `UP`
para sintaxis compatible con ese mínimo y `B` para errores comunes.
El formato mantiene los valores predeterminados de Ruff; no se excluyen reglas
ni archivos Python del proyecto. Para aplicar correcciones automáticas y formato:

```bash
uv run --locked ruff check --fix .
uv run --locked ruff format .
```

Revisa los cambios y ejecuta las comprobaciones y pruebas antes de enviarlos.
## Migración desde las funciones anteriores

Las pruebas comprueban el contrato HTTP de las funciones y los clientes.
Un servidor local permite verificar reutilización y cierre de conexiones,
además de concurrencia asíncrona. No consultan la API de producción.
Las dos funciones siguen disponibles con sus parámetros y respuestas habituales:

Para construir y comprobar los paquetes con las herramientas fijadas:
```python
from tu_ruc_python_client import get_contribuyente_by_ruc, get_contribuyente_by_search

```bash
uv build
uv run --locked twine check dist/*
print(get_contribuyente_by_search("juan perez", page=2))
print(get_contribuyente_by_ruc("5898204-3"))
```

`uv build` utiliza el backend `setuptools` fijado en `[build-system]`, en un
entorno de construcción aislado. Las dependencias del backend se resuelven
por separado del lockfile del proyecto.

Para añadir o quitar dependencias usa `uv add` y `uv remove`; para herramientas,
añade `--dev`. Para actualizar HTTPX dentro del rango permitido:
Cada llamada abre y cierra su propio cliente HTTP, sin timeout y siguiendo las
redirecciones, como antes. Para reutilizar conexiones entre consultas, migra a
`TuRucClient` o `AsyncTuRucClient`.

```bash
uv lock --upgrade-package httpx
uv sync --locked
uv run --locked python -m unittest discover -s tests -v
```
La biblioteca ya no usa Requests, sino HTTPX:

Revisa y versiona los cambios de `pyproject.toml` y `uv.lock` que correspondan.
- Cambia las capturas de `requests.exceptions.RequestException` por
`httpx.RequestError`.
- Si usabas `REQUESTS_CA_BUNDLE` para certificados propios, usa `SSL_CERT_FILE`
o `SSL_CERT_DIR`.
- Si tu proyecto usa Requests directamente, decláralo como dependencia propia.

Para comprobar que el wheel instala sus propias dependencias, usa otro entorno:
Consulta las [diferencias con Requests](https://www.python-httpx.org/compatibility/)
y las [variables de entorno de HTTPX](https://www.python-httpx.org/environment_variables/).

```bash
uv venv .venv-wheel
uv pip install --python .venv-wheel/bin/python dist/*.whl
uv pip check --python .venv-wheel/bin/python
.venv-wheel/bin/python -c 'import tu_ruc_python_client'
.venv-wheel/bin/python -m unittest discover -s tests -v
```
## Cambios

La CI exige lint y formato correctos antes de construir una vez y probar ese
wheel en entornos limpios de Python
3.11–3.15. Los tags `0.1.0` o `v0.1.0` deben coincidir con la versión del
paquete; sólo se publican en PyPI después de que toda la matriz pase, usando
`uv publish` con los mismos artefactos comprobados y el secreto `PYPI_TOKEN`
existente, expuesto al comando como `UV_PUBLISH_TOKEN`.
Consulta [CHANGELOG.md](https://github.com/ithdev/tu-ruc-python-client/blob/main/CHANGELOG.md)
para conocer los cambios de cada versión.

## Contribuciones

Las contribuciones son bienvenidas. Para cambios importantes, primero abra un problema para discutir lo que le gustaría cambiar.

¡Gracias por contribuir!
Las contribuciones son bienvenidas. Para cambios importantes, abre primero un
issue para comentar lo que te gustaría cambiar. Para preparar el entorno de
desarrollo, consulta
[CONTRIBUTING.md](https://github.com/ithdev/tu-ruc-python-client/blob/main/CONTRIBUTING.md).
Loading