From 93bde896bf875805e021770af6d3bad9b4155a7d Mon Sep 17 00:00:00 2001 From: Mijhael Samaniego <67170467+mijhaels@users.noreply.github.com> Date: Mon, 12 Oct 2026 19:08:22 -0300 Subject: [PATCH] docs: focus README on library users Move development, build and release instructions to CONTRIBUTING.md. Document validation and transport errors, and use absolute links so they resolve on PyPI. Co-Authored-By: Claude Opus 5.5 --- CONTRIBUTING.md | 92 +++++++++++++++++++++++++ README.md | 176 ++++++++++++++++-------------------------------- 2 files changed, 150 insertions(+), 118 deletions(-) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..c95cd88 --- /dev/null +++ b/CONTRIBUTING.md @@ -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). diff --git a/README.md b/README.md index 3f7c76b..9cd845d 100644 --- a/README.md +++ b/README.md @@ -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 @@ -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 @@ -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 @@ -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).