{"id":35171342,"url":"https://github.com/wells01440/numistalib","last_synced_at":"2026-01-13T21:04:37.297Z","repository":{"id":330880375,"uuid":"1117219531","full_name":"wells01440/numistalib","owner":"wells01440","description":"A cached API wrapper for Numista","archived":false,"fork":false,"pushed_at":"2025-12-29T01:28:52.000Z","size":7251,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-31T09:53:18.528Z","etag":null,"topics":["numismatics","numista"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/numistalib/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wells01440.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG","contributing":"docs/contributing.md","funding":null,"license":"license.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2025-12-16T02:16:32.000Z","updated_at":"2025-12-29T19:42:54.000Z","dependencies_parsed_at":"2025-12-31T18:07:17.459Z","dependency_job_id":null,"html_url":"https://github.com/wells01440/numistalib","commit_stats":null,"previous_names":["wells01440/numistalib"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/wells01440/numistalib","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wells01440%2Fnumistalib","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wells01440%2Fnumistalib/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wells01440%2Fnumistalib/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wells01440%2Fnumistalib/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wells01440","download_url":"https://codeload.github.com/wells01440/numistalib/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wells01440%2Fnumistalib/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28400863,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-13T14:36:09.778Z","status":"ssl_error","status_checked_at":"2026-01-13T14:35:19.697Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["numismatics","numista"],"created_at":"2025-12-28T20:57:41.637Z","updated_at":"2026-01-13T21:04:37.282Z","avatar_url":"https://github.com/wells01440.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# numistalib\n\n[![Tests](https://github.com/wells01440/numistalib/actions/workflows/test.yml/badge.svg)](https://github.com/wells01440/numistalib/actions/workflows/test.yml) [![Documentation Status](https://readthedocs.org/projects/numistalib/badge/?version=latest)](https://numistalib.readthedocs.io/en/latest/?badge=latest) [![PyPI](https://img.shields.io/pypi/v/numistalib)](https://pypi.org/project/numistalib/) [![Release](https://github.com/wells01440/numistalib/actions/workflows/release.yml/badge.svg)](https://github.com/wells01440/numistalib/actions/workflows/release.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n**A Python caching API wrapper for the Numista numismatic database with RFC 9111-compliant HTTP caching, intelligent rate limiting, and resilient retry logic.**\n\nIncludes an optional command-line interface with rich terminal output and sixel image support.\n\n## Overview\n\n[numistalib](https://pypi.org/project/numistalib/) is a **caching API client** for [Numista](https://en.numista.com), the collaborative online catalogue of world coins, banknotes, and exonumia. The library:\n\n- **Caches all GET requests** using [hishel](https://hishel.com) with configurable TTL (default 7 days)\n- **Rate limits** requests automatically (45 requests/minute by default) via [pyrate-limiter](https://github.com/vutran1710/PyrateLimiter)\n- **Retries failed requests** with exponential backoff and jitter using [tenacity](https://tenacity.readthedocs.io/)\n- **Validates all responses** with strict [Pydantic](https://docs.pydantic.dev/) models\n- **Provides both sync and async** client implementations via [httpx](https://www.python-httpx.org/)\n\nIncludes a CLI for interactive exploration with [Rich](https://rich.readthedocs.io/) terminal output and sixel protocol image display.\n\n## 📖 Documentation\n\n**[Read the Docs](https://numistalib.readthedocs.io/)** — Complete documentation with search, versioning, and offline formats.\n\n**Quick Links:**\n\n- [Installation](https://numistalib.readthedocs.io/en/latest/installation.html)\n- [Quickstart](https://numistalib.readthedocs.io/en/latest/quickstart.html)\n- [Python API Guide](https://numistalib.readthedocs.io/en/latest/python_api_guide.html)\n- [CLI Guide](https://numistalib.readthedocs.io/en/latest/cli_guide.html)\n- [API Reference](https://numistalib.readthedocs.io/en/latest/api/)\n- [Configuration](https://numistalib.readthedocs.io/en/latest/configuration.html)\n- [Architecture](https://numistalib.readthedocs.io/en/latest/architecture.html)\n\n## Features\n\n### Core API Features\n\n- **RFC 9111-Compliant HTTP Caching**: Persistent SQLite cache with configurable TTL and LRU eviction\n- **Intelligent Rate Limiting**: Transport-level throttling with configurable limits (respects Numista quotas)\n- **Resilient Retry Logic**: Exponential backoff with jitter for network failures and rate limit errors\n- **Complete Type Safety**: Full Pydantic v2 models with strict validation for all API entities\n- **Sync \u0026 Async Support**: Both synchronous and asynchronous client implementations\n- **Cache Indicators**: Visual feedback (💾/🌐) for cache hits/misses in responses\n\n### Optional CLI Features\n\n- **Rich Terminal UI**: Beautiful tables, panels, and formatted output via [Rich](https://rich.readthedocs.io/)\n- **Sixel Image Support**: Display coin images directly in terminal via sixel protocol ([textual-image](https://github.com/Textualize/textual-image))\n- **Flexible Display Modes**: Table or panel mode for different output preferences\n- **Command Aliases**: Short and long form commands (e.g., `catalogues` / `cat`)\n\n## Installation\n\n```bash\npip install numistalib\n# or with uv\nuv pip install numistalib\n```\n\nFor development:\n\n```bash\ngit clone https://github.com/wells01440/numistalib\ncd numistalib\nuv sync\n```\n\n## Configuration\n\n1. Get your API key from [Numista API](https://en.numista.com/api/)\n2. Set environment variable:\n\n   ```bash\n   export NUMISTA_API_KEY=your_api_key_here\n   ```\n\n   Or create `.env` file:\n\n   ```bash\n   cp .env.example .env\n   # Edit .env and add: NUMISTA_API_KEY=your_api_key_here\n   ```\n\n## Quick Start\n\n### Python API\n\n```python\nfrom numistalib.client import NumistaApiClient\nfrom numistalib.config import Settings\nfrom numistalib.services.types.service import TypeService\n\nsettings = Settings()  # Loads from environment/env file\n\nwith NumistaApiClient(settings) as client:\n    service = TypeService(client)\n    \n    # Search for types (cached automatically)\n    results = service.search_types(query=\"dollar\", page=1, count=10)\n    for coin_type in results:\n        print(f\"{coin_type.numista_id}: {coin_type.title}\")\n        print(f\"  Cached: {coin_type.cached_indicator}\")  # Shows 💾 or 🌐\n    \n    # Get full details with specifications\n    full_type = service.get_type(95420)\n    print(f\"Weight: {full_type.weight}g\")\n    print(f\"Composition: {full_type.composition}\")\n```\n\nSee [Python API Guide](https://numistalib.readthedocs.io/en/latest/python_api_guide.html) for complete examples.\n\n### CLI\n\nInteractive exploration with rich terminal output.\n\n#### Basic Commands\n\n```bash\n# Search for types\nnumistalib types search -q \"dollar\"\nnumistalib types search --issuer united-states --year 2020\n\n# Get detailed specifications\nnumistalib types get 95420\n\n# List available catalogues\nnumistalib catalogues\n\n# List issuers in different languages\nnumistalib issuers --lang es\n\n# View configuration\nnumistalib config list\n```\n\n#### Sixel Image Support\n\nThe CLI uses the [sixel protocol](https://en.wikipedia.org/wiki/Sixel) to display coin images in your terminal.\n\n**Sixel-compatible terminals:**\n\n- **[Kitty](https://sw.kovidgoyal.net/kitty/)** (macOS, Linux) — GPU-accelerated with full sixel support\n- **[WezTerm](https://wezfurlong.org/wezterm/)** (macOS, Linux, Windows) — GPU-accelerated, full sixel support\n- **[iTerm2](https://iterm2.com/)** (macOS) — Inline image display\n- **[mlterm](https://sourceforge.net/projects/mlterm/)** (Linux) — Lightweight sixel support\n- **[foot](https://codeberg.org/dnkl/foot)** (Linux/Wayland) — Fast, minimal\n- **[yaft](https://github.com/uobikiemukot/yaft)** (Linux framebuffer) — Console sixel\n\n**Testing Your Terminal:**\n\n```bash\n# Install imagemagick for testing\nconvert -size 100x100 xc:red sixel:- | cat\n```\n\nIf you see a red square, your terminal supports sixel! If not, the CLI will gracefully fall back to text-only output.\n\n**Example Output:**\n\n![Physical Specifications](docs/_static/cli_type_physical_specifications.png)\n\n![Obverse Details](docs/_static/cli_type_obverse_specifications.png)\n\n![Reverse Details](docs/_static/cli_type_reverse_specifications.png)\n\n![Edge Details](docs/_static/cli_type_edge_specifications.png)\n\nSee [CLI Guide](https://numistalib.readthedocs.io/en/latest/cli_guide.html) for complete command reference.\n\n## Architecture\n\nnumistalib follows a layered architecture optimized for caching efficiency and maintainability:\n\n- **client.py**: HTTP client layer with caching ([hishel](https://hishel.com)), rate limiting ([pyrate-limiter](https://github.com/vutran1710/PyrateLimiter)), and retry ([tenacity](https://tenacity.readthedocs.io/))\n- **services/**: Business logic per API endpoint, inheriting from abstract base classes\n- **models/**: Pydantic v2 models for strict API validation and type safety\n- **config.py**: Settings management with [pydantic-settings](https://docs.pydantic.dev/latest/concepts/pydantic_settings/)\n- **cli/**: Optional Click-based interface with [Rich](https://rich.readthedocs.io/) formatting and [textual-image](https://github.com/Textualize/textual-image) sixel support\n\nSee [Architecture Documentation](https://numistalib.readthedocs.io/en/latest/architecture.html) for detailed design patterns.\n\n## Built With\n\nnumistalib is built on excellent open-source libraries:\n\n### Core Dependencies\n\n- **[httpx](https://www.python-httpx.org/)** — Modern HTTP client with sync/async support\n- **[hishel](https://hishel.com)** — RFC 9111-compliant HTTP caching for httpx\n- **[pydantic](https://docs.pydantic.dev/)** — Data validation using Python type annotations\n- **[pydantic-settings](https://docs.pydantic.dev/latest/concepts/pydantic_settings/)** — Settings management\n- **[pyrate-limiter](https://github.com/vutran1710/PyrateLimiter)** — Rate limiting strategies\n- **[tenacity](https://tenacity.readthedocs.io/)** — Retrying library with configurable backoff\n\n### CLI Dependencies\n\n- **[click](https://click.palletsprojects.com/)** — Command-line interface creation kit\n- **[rich](https://rich.readthedocs.io/)** — Rich text and beautiful formatting in terminal\n- **[textual-image](https://github.com/Textualize/textual-image)** — Sixel protocol image rendering\n\n### Development Tools\n\n- **[uv](https://github.com/astral-sh/uv)** — Fast Python package installer and resolver\n- **[ruff](https://docs.astral.sh/ruff/)** — Fast Python linter and formatter\n- **[pytest](https://docs.pytest.org/)** — Testing framework\n- **[mypy](https://mypy-lang.org/)** \u0026 **[pyright](https://github.com/microsoft/pyright)** — Static type checkers\n\n## Contributing\n\nContributions are welcome! This project follows community best practices:\n\n1. **Code of Conduct**: Be respectful and inclusive\n2. **Issues**: Report bugs or request features via [GitHub Issues](https://github.com/wells01440/numistalib/issues)\n3. **Pull Requests**: Fork, branch, and submit PRs with clear descriptions\n4. **Code Quality**: All PRs must pass linting (ruff), type checking (mypy/pyright), and tests (pytest)\n5. **Documentation**: Update relevant docs for user-facing changes\n\nSee [Contributing Guide](https://numistalib.readthedocs.io/en/latest/contributing.html) and [AGENTS.md](AGENTS.md) for coding standards.\n\n## Community Standards\n\n- **License**: [MIT License](license.txt) — Free and open source\n- **Versioning**: [Semantic Versioning](https://semver.org/) (MAJOR.MINOR.PATCH)\n- **Changelog**: [Keep a Changelog](https://keepachangelog.com/) format in [CHANGELOG](CHANGELOG)\n- **Code Quality**: Enforced via CI (ruff, mypy, pyright, radon complexity checks)\n- **Testing**: Comprehensive test suite with pytest\n- **Documentation**: Complete user and API documentation on ReadTheDocs\n\n## Legal \u0026 Attribution\n\n### Numista\n\n- **Unofficial**: This library is an independent, community project and is **not affiliated with Numista**.\n- **Attribution**: Numista is a trademark/service of Numista. Please provide appropriate attribution when displaying data from Numista's API.\n- **Terms of Use**: Users must comply with Numista's published terms:\n  - [Conditions of Use](https://en.numista.com/conditions.php)\n  - [Legal Information](https://en.numista.com/legal.php)\n  - [Pricing API Terms](https://en.numista.com/api/pricing.php)\n- **Data Usage**: Follow Numista's guidelines for caching, rate limits, and redistribution. Configure TTL and cache behavior according to Numista's restrictions, especially for pricing data.\n- **Rate Limiting**: This project implements conservative rate limiting by default (45 requests/minute); always respect Numista's published limits and guidance.\n\n### License\n\nThis project is licensed under the [MIT License](license.txt). See the license file for details.\n\n---\n\n**Questions?** Check the [documentation](https://numistalib.readthedocs.io/) or [open an issue](https://github.com/wells01440/numistalib/issues).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwells01440%2Fnumistalib","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwells01440%2Fnumistalib","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwells01440%2Fnumistalib/lists"}