blur-placeholder


Nameblur-placeholder JSON
Version 0.1.2 PyPI version JSON
download
home_pageNone
SummaryGenerate blurred image placeholders for lazy loading
upload_time2025-07-24 10:26:57
maintainerNone
docs_urlNone
authorNone
requires_python>=3.7
license### `LICENSE` ```text MIT License Copyright (c) 2025 Brian Njoroge Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ```
keywords image placeholder blur lazy-loading
VCS
bugtrack_url
requirements accessible-pygments aiohappyeyeballs aiohttp aioredis aiosignal alabaster async-timeout attrs babel beautifulsoup4 black build certifi cffi charset-normalizer click coverage cryptography docutils flake8 frozenlist furo id idna imagesize iniconfig isort jaraco.classes jaraco.context jaraco.functools jeepney Jinja2 keyring markdown-it-py MarkupSafe mccabe mdurl more-itertools multidict mypy mypy_extensions nh3 packaging pathspec pillow platformdirs pluggy propcache pycodestyle pycparser pyflakes Pygments pyproject_hooks pytest pytest-asyncio pytest-cov pytest-mock readme_renderer requests requests-mock requests-toolbelt rfc3986 rich roman-numerals-py SecretStorage setuptools snowballstemmer soupsieve Sphinx sphinx-basic-ng sphinxcontrib-applehelp sphinxcontrib-devhelp sphinxcontrib-htmlhelp sphinxcontrib-jsmath sphinxcontrib-qthelp sphinxcontrib-serializinghtml twine typing_extensions urllib3 wheel yarl
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Blur Placeholder

[![PyPI version](https://badge.fury.io/py/blur-placeholder.svg)](https://badge.fury.io/py/blur-placeholder)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Python versions](https://img.shields.io/pypi/pyversions/blur-placeholder.svg)](https://pypi.org/project/blur-placeholder)

A simple, fast, and lightweight Python library to generate base64-encoded blurred image placeholders for lazy loading. This helps improve user experience by showing a low-quality version of an image while the full-quality version is loading.

## Key Features

- **Multiple Image Sources:** Generate placeholders from URLs, local file paths, or raw image bytes.
- **Asynchronous Support:** Built-in async support using `aiohttp` for non-blocking operations.
- **Caching:** In-memory caching to avoid regenerating placeholders for the same image.
- **Customizable:** Control the blur intensity, quality, and image format.
- **Lightweight:** Minimal dependencies (`Pillow` and `requests`).

## Installation

Install the basic version with synchronous support:

```bash
pip install blur-placeholder
```

For asynchronous support, install the `async` extra:

```bash
pip install blur-placeholder[async]
```

## Usage

### Synchronous

The synchronous `generate_blur_placeholder` function is ideal for simple scripts and applications where blocking operations are acceptable.

```python
from blur_placeholder import generate_blur_placeholder

# From a URL
data_url = generate_blur_placeholder("https://picsum.photos/seed/picsum/800/600")
print(data_url)

# From a local file
# with open("my_image.jpg", "wb") as f:
#     f.write(requests.get("https://picsum.photos/seed/picsum/800/600").content)
# data_url = generate_blur_placeholder("my_image.jpg")
# print(data_url)

# From image bytes
# with open("my_image.jpg", "rb") as f:
#     image_bytes = f.read()
# data_url = generate_blur_placeholder(image_bytes)
# print(data_url)
```

### Asynchronous

The asynchronous `generate_blur_placeholder_async` function is perfect for high-performance applications using `asyncio`.

```python
import asyncio
from blur_placeholder import generate_blur_placeholder_async

async def main():
    # From a URL
    data_url = await generate_blur_placeholder_async("https://picsum.photos/seed/picsum/800/600")
    print(data_url)

if __name__ == "__main__":
    asyncio.run(main())
```

### Advanced Usage

You can customize the placeholder generation with several optional parameters:

```python
data_url = generate_blur_placeholder(
    "https://picsum.photos/seed/picsum/800/600",
    blur_width=25,      # Width of the blurred image (default: 20)
    blur_radius=5,      # Blur radius (default: 2)
    quality=40,         # JPEG quality (default: 30)
    image_format="WEBP" # Output format (default: "JPEG")
)
```

## API Reference

### `generate_blur_placeholder(image_source, **kwargs)`

- `image_source` (str | bytes): The source of the image. Can be a URL, a local file path, or image data in bytes.
- `blur_width` (int, optional): The width to resize the image to before blurring. Defaults to `20`.
- `blur_radius` (int, optional): The radius for the Gaussian blur. Defaults to `2`.
- `quality` (int, optional): The quality of the output JPEG image (1-100). Defaults to `30`.
- `cache` (BaseCache, optional): A custom cache object. Defaults to a built-in in-memory cache.
- `timeout` (int, optional): The cache timeout in seconds. Defaults to `86400` (24 hours).
- `image_format` (str, optional): The output image format (e.g., "JPEG", "WEBP", "PNG"). Defaults to `"JPEG"`.

### `generate_blur_placeholder_async(image_source, **kwargs)`

This function has the same parameters as the synchronous version but is an `async` function.

## Caching

By default, `blur-placeholder` caches results in memory to speed up repeated requests for the same image. You can provide your own cache implementation by creating a class that inherits from `BaseCache` (for sync) or `BaseAsyncCache` (for async) and passing an instance to the `cache` parameter.

## Contributing

Contributions are welcome! To get started:

1.  Fork the repository.
2.  Clone your fork: `git clone https://github.com/your-username/blur-placeholder.git`
3.  Install the development dependencies: `pip install -e ".[dev]"`
4.  Run the tests: `pytest`

## License

This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "blur-placeholder",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.7",
    "maintainer_email": null,
    "keywords": "image, placeholder, blur, lazy-loading",
    "author": null,
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/c7/62/b7a4834e05426df08992f41daa4806f678a9a9f18dcee3f58fe7190fbec8/blur_placeholder-0.1.2.tar.gz",
    "platform": null,
    "description": "# Blur Placeholder\n\n[![PyPI version](https://badge.fury.io/py/blur-placeholder.svg)](https://badge.fury.io/py/blur-placeholder)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Python versions](https://img.shields.io/pypi/pyversions/blur-placeholder.svg)](https://pypi.org/project/blur-placeholder)\n\nA simple, fast, and lightweight Python library to generate base64-encoded blurred image placeholders for lazy loading. This helps improve user experience by showing a low-quality version of an image while the full-quality version is loading.\n\n## Key Features\n\n- **Multiple Image Sources:** Generate placeholders from URLs, local file paths, or raw image bytes.\n- **Asynchronous Support:** Built-in async support using `aiohttp` for non-blocking operations.\n- **Caching:** In-memory caching to avoid regenerating placeholders for the same image.\n- **Customizable:** Control the blur intensity, quality, and image format.\n- **Lightweight:** Minimal dependencies (`Pillow` and `requests`).\n\n## Installation\n\nInstall the basic version with synchronous support:\n\n```bash\npip install blur-placeholder\n```\n\nFor asynchronous support, install the `async` extra:\n\n```bash\npip install blur-placeholder[async]\n```\n\n## Usage\n\n### Synchronous\n\nThe synchronous `generate_blur_placeholder` function is ideal for simple scripts and applications where blocking operations are acceptable.\n\n```python\nfrom blur_placeholder import generate_blur_placeholder\n\n# From a URL\ndata_url = generate_blur_placeholder(\"https://picsum.photos/seed/picsum/800/600\")\nprint(data_url)\n\n# From a local file\n# with open(\"my_image.jpg\", \"wb\") as f:\n#     f.write(requests.get(\"https://picsum.photos/seed/picsum/800/600\").content)\n# data_url = generate_blur_placeholder(\"my_image.jpg\")\n# print(data_url)\n\n# From image bytes\n# with open(\"my_image.jpg\", \"rb\") as f:\n#     image_bytes = f.read()\n# data_url = generate_blur_placeholder(image_bytes)\n# print(data_url)\n```\n\n### Asynchronous\n\nThe asynchronous `generate_blur_placeholder_async` function is perfect for high-performance applications using `asyncio`.\n\n```python\nimport asyncio\nfrom blur_placeholder import generate_blur_placeholder_async\n\nasync def main():\n    # From a URL\n    data_url = await generate_blur_placeholder_async(\"https://picsum.photos/seed/picsum/800/600\")\n    print(data_url)\n\nif __name__ == \"__main__\":\n    asyncio.run(main())\n```\n\n### Advanced Usage\n\nYou can customize the placeholder generation with several optional parameters:\n\n```python\ndata_url = generate_blur_placeholder(\n    \"https://picsum.photos/seed/picsum/800/600\",\n    blur_width=25,      # Width of the blurred image (default: 20)\n    blur_radius=5,      # Blur radius (default: 2)\n    quality=40,         # JPEG quality (default: 30)\n    image_format=\"WEBP\" # Output format (default: \"JPEG\")\n)\n```\n\n## API Reference\n\n### `generate_blur_placeholder(image_source, **kwargs)`\n\n- `image_source` (str | bytes): The source of the image. Can be a URL, a local file path, or image data in bytes.\n- `blur_width` (int, optional): The width to resize the image to before blurring. Defaults to `20`.\n- `blur_radius` (int, optional): The radius for the Gaussian blur. Defaults to `2`.\n- `quality` (int, optional): The quality of the output JPEG image (1-100). Defaults to `30`.\n- `cache` (BaseCache, optional): A custom cache object. Defaults to a built-in in-memory cache.\n- `timeout` (int, optional): The cache timeout in seconds. Defaults to `86400` (24 hours).\n- `image_format` (str, optional): The output image format (e.g., \"JPEG\", \"WEBP\", \"PNG\"). Defaults to `\"JPEG\"`.\n\n### `generate_blur_placeholder_async(image_source, **kwargs)`\n\nThis function has the same parameters as the synchronous version but is an `async` function.\n\n## Caching\n\nBy default, `blur-placeholder` caches results in memory to speed up repeated requests for the same image. You can provide your own cache implementation by creating a class that inherits from `BaseCache` (for sync) or `BaseAsyncCache` (for async) and passing an instance to the `cache` parameter.\n\n## Contributing\n\nContributions are welcome! To get started:\n\n1.  Fork the repository.\n2.  Clone your fork: `git clone https://github.com/your-username/blur-placeholder.git`\n3.  Install the development dependencies: `pip install -e \".[dev]\"`\n4.  Run the tests: `pytest`\n\n## License\n\nThis project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.\n",
    "bugtrack_url": null,
    "license": "### `LICENSE`\n        \n        ```text\n        MIT License\n        \n        Copyright (c) 2025 Brian Njoroge\n        \n        Permission is hereby granted, free of charge, to any person obtaining a copy\n        of this software and associated documentation files (the \"Software\"), to deal\n        in the Software without restriction, including without limitation the rights\n        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n        copies of the Software, and to permit persons to whom the Software is\n        furnished to do so, subject to the following conditions:\n        \n        The above copyright notice and this permission notice shall be included in all\n        copies or substantial portions of the Software.\n        \n        THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n        SOFTWARE.\n        ```\n        ",
    "summary": "Generate blurred image placeholders for lazy loading",
    "version": "0.1.2",
    "project_urls": {
        "BugTracker": "https://github.com/Njoro410/blur_placeholder/issues",
        "Documentation": "https://github.com/Njoro410/blur_placeholder#readme",
        "Homepage": "https://github.com/Njoro410/blur_placeholder"
    },
    "split_keywords": [
        "image",
        " placeholder",
        " blur",
        " lazy-loading"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "c104d45f4706e9f61005d35f33f6eb5bcb8304fd18de6be3ea1a00e036970bae",
                "md5": "9b900c3faf416bd74a2f7c092772d816",
                "sha256": "fd65de2468dd5d04d3ff1a82867b1cd3d50a83b12b1d8ff391cd7bea4554b1a0"
            },
            "downloads": -1,
            "filename": "blur_placeholder-0.1.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "9b900c3faf416bd74a2f7c092772d816",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7",
            "size": 8641,
            "upload_time": "2025-07-24T10:26:55",
            "upload_time_iso_8601": "2025-07-24T10:26:55.782402Z",
            "url": "https://files.pythonhosted.org/packages/c1/04/d45f4706e9f61005d35f33f6eb5bcb8304fd18de6be3ea1a00e036970bae/blur_placeholder-0.1.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "c762b7a4834e05426df08992f41daa4806f678a9a9f18dcee3f58fe7190fbec8",
                "md5": "993c8aeb53c5bd6a208ffba5e13d319f",
                "sha256": "0f54b05d705611746bb08b745bb9f0ea7d5c21a2174adb54f957983ad4f0d7fc"
            },
            "downloads": -1,
            "filename": "blur_placeholder-0.1.2.tar.gz",
            "has_sig": false,
            "md5_digest": "993c8aeb53c5bd6a208ffba5e13d319f",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.7",
            "size": 9829,
            "upload_time": "2025-07-24T10:26:57",
            "upload_time_iso_8601": "2025-07-24T10:26:57.305990Z",
            "url": "https://files.pythonhosted.org/packages/c7/62/b7a4834e05426df08992f41daa4806f678a9a9f18dcee3f58fe7190fbec8/blur_placeholder-0.1.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-07-24 10:26:57",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "Njoro410",
    "github_project": "blur_placeholder",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "requirements": [
        {
            "name": "accessible-pygments",
            "specs": [
                [
                    "==",
                    "0.0.5"
                ]
            ]
        },
        {
            "name": "aiohappyeyeballs",
            "specs": [
                [
                    "==",
                    "2.6.1"
                ]
            ]
        },
        {
            "name": "aiohttp",
            "specs": [
                [
                    "==",
                    "3.12.14"
                ]
            ]
        },
        {
            "name": "aioredis",
            "specs": [
                [
                    "==",
                    "2.0.1"
                ]
            ]
        },
        {
            "name": "aiosignal",
            "specs": [
                [
                    "==",
                    "1.4.0"
                ]
            ]
        },
        {
            "name": "alabaster",
            "specs": [
                [
                    "==",
                    "1.0.0"
                ]
            ]
        },
        {
            "name": "async-timeout",
            "specs": [
                [
                    "==",
                    "5.0.1"
                ]
            ]
        },
        {
            "name": "attrs",
            "specs": [
                [
                    "==",
                    "25.3.0"
                ]
            ]
        },
        {
            "name": "babel",
            "specs": [
                [
                    "==",
                    "2.17.0"
                ]
            ]
        },
        {
            "name": "beautifulsoup4",
            "specs": [
                [
                    "==",
                    "4.13.4"
                ]
            ]
        },
        {
            "name": "black",
            "specs": [
                [
                    "==",
                    "25.1.0"
                ]
            ]
        },
        {
            "name": "build",
            "specs": [
                [
                    "==",
                    "1.2.2.post1"
                ]
            ]
        },
        {
            "name": "certifi",
            "specs": [
                [
                    "==",
                    "2025.7.14"
                ]
            ]
        },
        {
            "name": "cffi",
            "specs": [
                [
                    "==",
                    "1.17.1"
                ]
            ]
        },
        {
            "name": "charset-normalizer",
            "specs": [
                [
                    "==",
                    "3.4.2"
                ]
            ]
        },
        {
            "name": "click",
            "specs": [
                [
                    "==",
                    "8.2.1"
                ]
            ]
        },
        {
            "name": "coverage",
            "specs": [
                [
                    "==",
                    "7.9.2"
                ]
            ]
        },
        {
            "name": "cryptography",
            "specs": [
                [
                    "==",
                    "45.0.5"
                ]
            ]
        },
        {
            "name": "docutils",
            "specs": [
                [
                    "==",
                    "0.21.2"
                ]
            ]
        },
        {
            "name": "flake8",
            "specs": [
                [
                    "==",
                    "7.3.0"
                ]
            ]
        },
        {
            "name": "frozenlist",
            "specs": [
                [
                    "==",
                    "1.7.0"
                ]
            ]
        },
        {
            "name": "furo",
            "specs": [
                [
                    "==",
                    "2025.7.19"
                ]
            ]
        },
        {
            "name": "id",
            "specs": [
                [
                    "==",
                    "1.5.0"
                ]
            ]
        },
        {
            "name": "idna",
            "specs": [
                [
                    "==",
                    "3.10"
                ]
            ]
        },
        {
            "name": "imagesize",
            "specs": [
                [
                    "==",
                    "1.4.1"
                ]
            ]
        },
        {
            "name": "iniconfig",
            "specs": [
                [
                    "==",
                    "2.1.0"
                ]
            ]
        },
        {
            "name": "isort",
            "specs": [
                [
                    "==",
                    "6.0.1"
                ]
            ]
        },
        {
            "name": "jaraco.classes",
            "specs": [
                [
                    "==",
                    "3.4.0"
                ]
            ]
        },
        {
            "name": "jaraco.context",
            "specs": [
                [
                    "==",
                    "6.0.1"
                ]
            ]
        },
        {
            "name": "jaraco.functools",
            "specs": [
                [
                    "==",
                    "4.2.1"
                ]
            ]
        },
        {
            "name": "jeepney",
            "specs": [
                [
                    "==",
                    "0.9.0"
                ]
            ]
        },
        {
            "name": "Jinja2",
            "specs": [
                [
                    "==",
                    "3.1.6"
                ]
            ]
        },
        {
            "name": "keyring",
            "specs": [
                [
                    "==",
                    "25.6.0"
                ]
            ]
        },
        {
            "name": "markdown-it-py",
            "specs": [
                [
                    "==",
                    "3.0.0"
                ]
            ]
        },
        {
            "name": "MarkupSafe",
            "specs": [
                [
                    "==",
                    "3.0.2"
                ]
            ]
        },
        {
            "name": "mccabe",
            "specs": [
                [
                    "==",
                    "0.7.0"
                ]
            ]
        },
        {
            "name": "mdurl",
            "specs": [
                [
                    "==",
                    "0.1.2"
                ]
            ]
        },
        {
            "name": "more-itertools",
            "specs": [
                [
                    "==",
                    "10.7.0"
                ]
            ]
        },
        {
            "name": "multidict",
            "specs": [
                [
                    "==",
                    "6.6.3"
                ]
            ]
        },
        {
            "name": "mypy",
            "specs": [
                [
                    "==",
                    "1.17.0"
                ]
            ]
        },
        {
            "name": "mypy_extensions",
            "specs": [
                [
                    "==",
                    "1.1.0"
                ]
            ]
        },
        {
            "name": "nh3",
            "specs": [
                [
                    "==",
                    "0.3.0"
                ]
            ]
        },
        {
            "name": "packaging",
            "specs": [
                [
                    "==",
                    "25.0"
                ]
            ]
        },
        {
            "name": "pathspec",
            "specs": [
                [
                    "==",
                    "0.12.1"
                ]
            ]
        },
        {
            "name": "pillow",
            "specs": [
                [
                    "==",
                    "11.3.0"
                ]
            ]
        },
        {
            "name": "platformdirs",
            "specs": [
                [
                    "==",
                    "4.3.8"
                ]
            ]
        },
        {
            "name": "pluggy",
            "specs": [
                [
                    "==",
                    "1.6.0"
                ]
            ]
        },
        {
            "name": "propcache",
            "specs": [
                [
                    "==",
                    "0.3.2"
                ]
            ]
        },
        {
            "name": "pycodestyle",
            "specs": [
                [
                    "==",
                    "2.14.0"
                ]
            ]
        },
        {
            "name": "pycparser",
            "specs": [
                [
                    "==",
                    "2.22"
                ]
            ]
        },
        {
            "name": "pyflakes",
            "specs": [
                [
                    "==",
                    "3.4.0"
                ]
            ]
        },
        {
            "name": "Pygments",
            "specs": [
                [
                    "==",
                    "2.19.2"
                ]
            ]
        },
        {
            "name": "pyproject_hooks",
            "specs": [
                [
                    "==",
                    "1.2.0"
                ]
            ]
        },
        {
            "name": "pytest",
            "specs": [
                [
                    "==",
                    "8.4.1"
                ]
            ]
        },
        {
            "name": "pytest-asyncio",
            "specs": [
                [
                    "==",
                    "1.1.0"
                ]
            ]
        },
        {
            "name": "pytest-cov",
            "specs": [
                [
                    "==",
                    "6.2.1"
                ]
            ]
        },
        {
            "name": "pytest-mock",
            "specs": [
                [
                    "==",
                    "3.14.1"
                ]
            ]
        },
        {
            "name": "readme_renderer",
            "specs": [
                [
                    "==",
                    "44.0"
                ]
            ]
        },
        {
            "name": "requests",
            "specs": [
                [
                    "==",
                    "2.32.4"
                ]
            ]
        },
        {
            "name": "requests-mock",
            "specs": [
                [
                    "==",
                    "1.12.1"
                ]
            ]
        },
        {
            "name": "requests-toolbelt",
            "specs": [
                [
                    "==",
                    "1.0.0"
                ]
            ]
        },
        {
            "name": "rfc3986",
            "specs": [
                [
                    "==",
                    "2.0.0"
                ]
            ]
        },
        {
            "name": "rich",
            "specs": [
                [
                    "==",
                    "14.0.0"
                ]
            ]
        },
        {
            "name": "roman-numerals-py",
            "specs": [
                [
                    "==",
                    "3.1.0"
                ]
            ]
        },
        {
            "name": "SecretStorage",
            "specs": [
                [
                    "==",
                    "3.3.3"
                ]
            ]
        },
        {
            "name": "setuptools",
            "specs": [
                [
                    "==",
                    "80.9.0"
                ]
            ]
        },
        {
            "name": "snowballstemmer",
            "specs": [
                [
                    "==",
                    "3.0.1"
                ]
            ]
        },
        {
            "name": "soupsieve",
            "specs": [
                [
                    "==",
                    "2.7"
                ]
            ]
        },
        {
            "name": "Sphinx",
            "specs": [
                [
                    "==",
                    "8.2.3"
                ]
            ]
        },
        {
            "name": "sphinx-basic-ng",
            "specs": [
                [
                    "==",
                    "1.0.0b2"
                ]
            ]
        },
        {
            "name": "sphinxcontrib-applehelp",
            "specs": [
                [
                    "==",
                    "2.0.0"
                ]
            ]
        },
        {
            "name": "sphinxcontrib-devhelp",
            "specs": [
                [
                    "==",
                    "2.0.0"
                ]
            ]
        },
        {
            "name": "sphinxcontrib-htmlhelp",
            "specs": [
                [
                    "==",
                    "2.1.0"
                ]
            ]
        },
        {
            "name": "sphinxcontrib-jsmath",
            "specs": [
                [
                    "==",
                    "1.0.1"
                ]
            ]
        },
        {
            "name": "sphinxcontrib-qthelp",
            "specs": [
                [
                    "==",
                    "2.0.0"
                ]
            ]
        },
        {
            "name": "sphinxcontrib-serializinghtml",
            "specs": [
                [
                    "==",
                    "2.0.0"
                ]
            ]
        },
        {
            "name": "twine",
            "specs": [
                [
                    "==",
                    "6.1.0"
                ]
            ]
        },
        {
            "name": "typing_extensions",
            "specs": [
                [
                    "==",
                    "4.14.1"
                ]
            ]
        },
        {
            "name": "urllib3",
            "specs": [
                [
                    "==",
                    "2.5.0"
                ]
            ]
        },
        {
            "name": "wheel",
            "specs": [
                [
                    "==",
                    "0.45.1"
                ]
            ]
        },
        {
            "name": "yarl",
            "specs": [
                [
                    "==",
                    "1.20.1"
                ]
            ]
        }
    ],
    "lcname": "blur-placeholder"
}
        
Elapsed time: 1.78550s