diff --git a/media_manager/main.py b/media_manager/main.py index 9cc33e2..8f85da3 100644 --- a/media_manager/main.py +++ b/media_manager/main.py @@ -52,8 +52,9 @@ from media_manager.tv.service import ( auto_download_all_approved_season_requests, import_all_torrents, ) -import media_manager.torrent.router as torrent_router from media_manager.config import BasicConfig + +import media_manager.torrent.router as torrent_router from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from datetime import datetime @@ -80,8 +81,9 @@ def hourly_tasks(): auto_download_all_approved_season_requests() import_all_torrents() + scheduler = BackgroundScheduler() -trigger = CronTrigger(second=0, hour="*") +trigger = CronTrigger(minute=0, hour="*") scheduler.add_job(hourly_tasks, trigger) scheduler.start() @@ -180,7 +182,6 @@ if openid_client is not None: app.include_router(tv_router.router, prefix="/tv", tags=["tv"]) app.include_router(torrent_router.router, prefix="/torrent", tags=["torrent"]) -# static file routers app.mount( "/static/image", StaticFiles(directory=basic_config.image_directory), diff --git a/media_manager/metadataProvider/utils.py b/media_manager/metadataProvider/utils.py index 3cf8615..b533f87 100644 --- a/media_manager/metadataProvider/utils.py +++ b/media_manager/metadataProvider/utils.py @@ -1,8 +1,7 @@ -import mimetypes - +from PIL import Image +import pillow_avif import requests - def get_year_from_first_air_date(first_air_date: str | None) -> int | None: if first_air_date: return int(first_air_date.split("-")[0]) @@ -12,11 +11,14 @@ def get_year_from_first_air_date(first_air_date: str | None) -> int | None: def download_poster_image(storage_path=None, poster_url=None, show=None) -> bool: res = requests.get(poster_url, stream=True) - content_type = res.headers["content-type"] - file_extension = mimetypes.guess_extension(content_type) if res.status_code == 200: - with open(storage_path.joinpath(str(show.id) + file_extension), "wb") as f: + image_file_path = storage_path.joinpath(str(show.id)) + with open( str(image_file_path)+".jpg", "wb") as f: f.write(res.content) + + original_image = Image.open(str(image_file_path)+".jpg") + original_image.save(str(image_file_path)+".avif", quality=50) + original_image.save(str(image_file_path)+".webp", quality=50) return True else: return False diff --git a/media_manager/torrent/dependencies.py b/media_manager/torrent/dependencies.py index df025af..76bb96b 100644 --- a/media_manager/torrent/dependencies.py +++ b/media_manager/torrent/dependencies.py @@ -2,7 +2,7 @@ from typing import Annotated from fastapi import Depends -from exceptions import NotFoundError +from media_manager.exceptions import NotFoundError from media_manager.database import DbSessionDependency from media_manager.torrent.service import TorrentService from media_manager.torrent.repository import TorrentRepository diff --git a/media_manager/tv/router.py b/media_manager/tv/router.py index 6b1f38d..8006615 100644 --- a/media_manager/tv/router.py +++ b/media_manager/tv/router.py @@ -24,10 +24,10 @@ from media_manager.tv.schemas import ( RichSeasonRequest, ) from media_manager.tv.dependencies import ( - torrent_service_dep, season_dep, show_dep, tv_repository_dep, + tv_service_dep, ) router = APIRouter() @@ -51,7 +51,7 @@ router = APIRouter() }, ) def add_a_show( - tv_service: torrent_service_dep, show_id: int, metadata_provider: str = "tmdb" + tv_service: tv_service_dep, show_id: int, metadata_provider: str = "tmdb" ): try: show = tv_service.add_show( @@ -83,7 +83,7 @@ def delete_a_show(tv_repository: tv_repository_dep, show_id: ShowId): "/shows", dependencies=[Depends(current_active_user)], response_model=list[Show] ) def get_all_shows( - tv_service: torrent_service_dep, external_id: int = None, metadata_provider: str = "tmdb" + tv_service: tv_service_dep, external_id: int = None, metadata_provider: str = "tmdb" ): if external_id is not None: return tv_service.get_show_by_external_id( @@ -98,7 +98,7 @@ def get_all_shows( dependencies=[Depends(current_active_user)], response_model=list[RichShowTorrent], ) -def get_shows_with_torrents(tv_service: torrent_service_dep): +def get_shows_with_torrents(tv_service: tv_service_dep): """ get all shows that are associated with torrents :return: A list of shows with all their torrents @@ -112,7 +112,7 @@ def get_shows_with_torrents(tv_service: torrent_service_dep): dependencies=[Depends(current_active_user)], response_model=PublicShow, ) -def get_a_show(show: show_dep, tv_service: torrent_service_dep) -> PublicShow: +def get_a_show(show: show_dep, tv_service: tv_service_dep) -> PublicShow: return tv_service.get_public_show_by_id(show_id=show.id) @@ -121,7 +121,7 @@ def get_a_show(show: show_dep, tv_service: torrent_service_dep) -> PublicShow: dependencies=[Depends(current_active_user)], response_model=RichShowTorrent, ) -def get_a_shows_torrents(show: show_dep, tv_service: torrent_service_dep): +def get_a_shows_torrents(show: show_dep, tv_service: tv_service_dep): return tv_service.get_torrents_for_show(show=show) @@ -134,7 +134,7 @@ def get_a_shows_torrents(show: show_dep, tv_service: torrent_service_dep): def request_a_season( user: Annotated[User, Depends(current_active_user)], season_request: CreateSeasonRequest, - tv_service: torrent_service_dep, + tv_service: tv_service_dep, ): """ adds request flag to a season @@ -156,7 +156,7 @@ def request_a_season( dependencies=[Depends(current_active_user)], response_model=list[RichSeasonRequest], ) -def get_season_requests(tv_service: torrent_service_dep) -> list[RichSeasonRequest]: +def get_season_requests(tv_service: tv_service_dep) -> list[RichSeasonRequest]: return tv_service.get_all_season_requests() @@ -165,7 +165,7 @@ def get_season_requests(tv_service: torrent_service_dep) -> list[RichSeasonReque status_code=status.HTTP_204_NO_CONTENT, ) def delete_season_request( - tv_service: torrent_service_dep, + tv_service: tv_service_dep, user: Annotated[User, Depends(current_active_user)], request_id: SeasonRequestId, ): @@ -188,7 +188,7 @@ def delete_season_request( "/seasons/requests/{season_request_id}", status_code=status.HTTP_204_NO_CONTENT ) def authorize_request( - tv_service: torrent_service_dep, + tv_service: tv_service_dep, user: Annotated[User, Depends(current_superuser)], season_request_id: SeasonRequestId, authorized_status: bool = False, @@ -209,7 +209,7 @@ def authorize_request( @router.put("/seasons/requests", status_code=status.HTTP_204_NO_CONTENT) def update_request( - tv_service: torrent_service_dep, + tv_service: tv_service_dep, user: Annotated[User, Depends(current_active_user)], season_request: UpdateSeasonRequest, ): @@ -229,7 +229,7 @@ def update_request( response_model=list[PublicSeasonFile], ) def get_season_files( - season: season_dep, tv_service: torrent_service_dep + season: season_dep, tv_service: tv_service_dep ) -> list[PublicSeasonFile]: return tv_service.get_public_season_files_by_season_id(season_id=season.id) @@ -247,7 +247,7 @@ def get_season_files( response_model=list[PublicIndexerQueryResult], ) def get_torrents_for_a_season( - tv_service: torrent_service_dep, + tv_service: tv_service_dep, show_id: ShowId, season_number: int = 1, search_query_override: str = None, @@ -267,7 +267,7 @@ def get_torrents_for_a_season( dependencies=[Depends(current_superuser)], ) def download_a_torrent( - tv_service: torrent_service_dep, + tv_service: tv_service_dep, public_indexer_result_id: IndexerQueryResultId, show_id: ShowId, override_file_path_suffix: str = "", @@ -290,7 +290,7 @@ def download_a_torrent( response_model=list[MetaDataProviderShowSearchResult], ) def search_metadata_providers_for_a_show( - tv_service: torrent_service_dep, query: str, metadata_provider: str = "tmdb" + tv_service: tv_service_dep, query: str, metadata_provider: str = "tmdb" ): return tv_service.search_for_show(query=query, metadata_provider=metadata_provider) @@ -300,5 +300,5 @@ def search_metadata_providers_for_a_show( dependencies=[Depends(current_active_user)], response_model=list[MetaDataProviderShowSearchResult], ) -def get_recommended_shows(tv_service: torrent_service_dep, metadata_provider: str = "tmdb"): +def get_recommended_shows(tv_service: tv_service_dep, metadata_provider: str = "tmdb"): return tv_service.get_popular_shows(metadata_provider=metadata_provider) diff --git a/pyproject.toml b/pyproject.toml index 96a395b..aabf1f0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,4 +29,6 @@ dependencies = [ "apscheduler>=3.11.0", "alembic>=1.16.1", "pytest>=8.4.0", + "pillow>=11.2.1", + "pillow-avif-plugin>=1.5.2", ] diff --git a/uv.lock b/uv.lock index 59003cc..e0c174c 100644 --- a/uv.lock +++ b/uv.lock @@ -634,6 +634,8 @@ dependencies = [ { name = "httpx-oauth" }, { name = "jsonschema" }, { name = "patool" }, + { name = "pillow" }, + { name = "pillow-avif-plugin" }, { name = "psycopg", extra = ["binary"] }, { name = "pydantic" }, { name = "pydantic-settings" }, @@ -663,6 +665,8 @@ requires-dist = [ { name = "httpx-oauth", specifier = ">=0.16.1" }, { name = "jsonschema", specifier = ">=4.24.0" }, { name = "patool", specifier = ">=4.0.1" }, + { name = "pillow", specifier = ">=11.2.1" }, + { name = "pillow-avif-plugin", specifier = ">=1.5.2" }, { name = "psycopg", extras = ["binary"], specifier = ">=3.2.9" }, { name = "pydantic", specifier = ">=2.11.5" }, { name = "pydantic-settings", specifier = ">=2.9.1" }, @@ -705,6 +709,62 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d2/07/a7aefd5b3ee565b4d959bcf7061666c7fbf66ed83e58d07cdcdca35c9b33/patool-4.0.1-py2.py3-none-any.whl", hash = "sha256:a7430eb08edcbd71feaf9c40f55c46f6a0ac385dc68dd0f5010cfa4ad2e9341a", size = 86512, upload-time = "2025-05-02T19:08:19.407Z" }, ] +[[package]] +name = "pillow" +version = "11.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/af/cb/bb5c01fcd2a69335b86c22142b2bccfc3464087efb7fd382eee5ffc7fdf7/pillow-11.2.1.tar.gz", hash = "sha256:a64dd61998416367b7ef979b73d3a85853ba9bec4c2925f74e588879a58716b6", size = 47026707, upload-time = "2025-04-12T17:50:03.289Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/36/9c/447528ee3776e7ab8897fe33697a7ff3f0475bb490c5ac1456a03dc57956/pillow-11.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fdec757fea0b793056419bca3e9932eb2b0ceec90ef4813ea4c1e072c389eb28", size = 3190098, upload-time = "2025-04-12T17:48:23.915Z" }, + { url = "https://files.pythonhosted.org/packages/b5/09/29d5cd052f7566a63e5b506fac9c60526e9ecc553825551333e1e18a4858/pillow-11.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b0e130705d568e2f43a17bcbe74d90958e8a16263868a12c3e0d9c8162690830", size = 3030166, upload-time = "2025-04-12T17:48:25.738Z" }, + { url = "https://files.pythonhosted.org/packages/71/5d/446ee132ad35e7600652133f9c2840b4799bbd8e4adba881284860da0a36/pillow-11.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bdb5e09068332578214cadd9c05e3d64d99e0e87591be22a324bdbc18925be0", size = 4408674, upload-time = "2025-04-12T17:48:27.908Z" }, + { url = "https://files.pythonhosted.org/packages/69/5f/cbe509c0ddf91cc3a03bbacf40e5c2339c4912d16458fcb797bb47bcb269/pillow-11.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d189ba1bebfbc0c0e529159631ec72bb9e9bc041f01ec6d3233d6d82eb823bc1", size = 4496005, upload-time = "2025-04-12T17:48:29.888Z" }, + { url = "https://files.pythonhosted.org/packages/f9/b3/dd4338d8fb8a5f312021f2977fb8198a1184893f9b00b02b75d565c33b51/pillow-11.2.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:191955c55d8a712fab8934a42bfefbf99dd0b5875078240943f913bb66d46d9f", size = 4518707, upload-time = "2025-04-12T17:48:31.874Z" }, + { url = "https://files.pythonhosted.org/packages/13/eb/2552ecebc0b887f539111c2cd241f538b8ff5891b8903dfe672e997529be/pillow-11.2.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:ad275964d52e2243430472fc5d2c2334b4fc3ff9c16cb0a19254e25efa03a155", size = 4610008, upload-time = "2025-04-12T17:48:34.422Z" }, + { url = "https://files.pythonhosted.org/packages/72/d1/924ce51bea494cb6e7959522d69d7b1c7e74f6821d84c63c3dc430cbbf3b/pillow-11.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:750f96efe0597382660d8b53e90dd1dd44568a8edb51cb7f9d5d918b80d4de14", size = 4585420, upload-time = "2025-04-12T17:48:37.641Z" }, + { url = "https://files.pythonhosted.org/packages/43/ab/8f81312d255d713b99ca37479a4cb4b0f48195e530cdc1611990eb8fd04b/pillow-11.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fe15238d3798788d00716637b3d4e7bb6bde18b26e5d08335a96e88564a36b6b", size = 4667655, upload-time = "2025-04-12T17:48:39.652Z" }, + { url = "https://files.pythonhosted.org/packages/94/86/8f2e9d2dc3d308dfd137a07fe1cc478df0a23d42a6c4093b087e738e4827/pillow-11.2.1-cp313-cp313-win32.whl", hash = "sha256:3fe735ced9a607fee4f481423a9c36701a39719252a9bb251679635f99d0f7d2", size = 2332329, upload-time = "2025-04-12T17:48:41.765Z" }, + { url = "https://files.pythonhosted.org/packages/6d/ec/1179083b8d6067a613e4d595359b5fdea65d0a3b7ad623fee906e1b3c4d2/pillow-11.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:74ee3d7ecb3f3c05459ba95eed5efa28d6092d751ce9bf20e3e253a4e497e691", size = 2676388, upload-time = "2025-04-12T17:48:43.625Z" }, + { url = "https://files.pythonhosted.org/packages/23/f1/2fc1e1e294de897df39fa8622d829b8828ddad938b0eaea256d65b84dd72/pillow-11.2.1-cp313-cp313-win_arm64.whl", hash = "sha256:5119225c622403afb4b44bad4c1ca6c1f98eed79db8d3bc6e4e160fc6339d66c", size = 2414950, upload-time = "2025-04-12T17:48:45.475Z" }, + { url = "https://files.pythonhosted.org/packages/c4/3e/c328c48b3f0ead7bab765a84b4977acb29f101d10e4ef57a5e3400447c03/pillow-11.2.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8ce2e8411c7aaef53e6bb29fe98f28cd4fbd9a1d9be2eeea434331aac0536b22", size = 3192759, upload-time = "2025-04-12T17:48:47.866Z" }, + { url = "https://files.pythonhosted.org/packages/18/0e/1c68532d833fc8b9f404d3a642991441d9058eccd5606eab31617f29b6d4/pillow-11.2.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:9ee66787e095127116d91dea2143db65c7bb1e232f617aa5957c0d9d2a3f23a7", size = 3033284, upload-time = "2025-04-12T17:48:50.189Z" }, + { url = "https://files.pythonhosted.org/packages/b7/cb/6faf3fb1e7705fd2db74e070f3bf6f88693601b0ed8e81049a8266de4754/pillow-11.2.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9622e3b6c1d8b551b6e6f21873bdcc55762b4b2126633014cea1803368a9aa16", size = 4445826, upload-time = "2025-04-12T17:48:52.346Z" }, + { url = "https://files.pythonhosted.org/packages/07/94/8be03d50b70ca47fb434a358919d6a8d6580f282bbb7af7e4aa40103461d/pillow-11.2.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63b5dff3a68f371ea06025a1a6966c9a1e1ee452fc8020c2cd0ea41b83e9037b", size = 4527329, upload-time = "2025-04-12T17:48:54.403Z" }, + { url = "https://files.pythonhosted.org/packages/fd/a4/bfe78777076dc405e3bd2080bc32da5ab3945b5a25dc5d8acaa9de64a162/pillow-11.2.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:31df6e2d3d8fc99f993fd253e97fae451a8db2e7207acf97859732273e108406", size = 4549049, upload-time = "2025-04-12T17:48:56.383Z" }, + { url = "https://files.pythonhosted.org/packages/65/4d/eaf9068dc687c24979e977ce5677e253624bd8b616b286f543f0c1b91662/pillow-11.2.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:062b7a42d672c45a70fa1f8b43d1d38ff76b63421cbbe7f88146b39e8a558d91", size = 4635408, upload-time = "2025-04-12T17:48:58.782Z" }, + { url = "https://files.pythonhosted.org/packages/1d/26/0fd443365d9c63bc79feb219f97d935cd4b93af28353cba78d8e77b61719/pillow-11.2.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4eb92eca2711ef8be42fd3f67533765d9fd043b8c80db204f16c8ea62ee1a751", size = 4614863, upload-time = "2025-04-12T17:49:00.709Z" }, + { url = "https://files.pythonhosted.org/packages/49/65/dca4d2506be482c2c6641cacdba5c602bc76d8ceb618fd37de855653a419/pillow-11.2.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f91ebf30830a48c825590aede79376cb40f110b387c17ee9bd59932c961044f9", size = 4692938, upload-time = "2025-04-12T17:49:02.946Z" }, + { url = "https://files.pythonhosted.org/packages/b3/92/1ca0c3f09233bd7decf8f7105a1c4e3162fb9142128c74adad0fb361b7eb/pillow-11.2.1-cp313-cp313t-win32.whl", hash = "sha256:e0b55f27f584ed623221cfe995c912c61606be8513bfa0e07d2c674b4516d9dd", size = 2335774, upload-time = "2025-04-12T17:49:04.889Z" }, + { url = "https://files.pythonhosted.org/packages/a5/ac/77525347cb43b83ae905ffe257bbe2cc6fd23acb9796639a1f56aa59d191/pillow-11.2.1-cp313-cp313t-win_amd64.whl", hash = "sha256:36d6b82164c39ce5482f649b437382c0fb2395eabc1e2b1702a6deb8ad647d6e", size = 2681895, upload-time = "2025-04-12T17:49:06.635Z" }, + { url = "https://files.pythonhosted.org/packages/67/32/32dc030cfa91ca0fc52baebbba2e009bb001122a1daa8b6a79ad830b38d3/pillow-11.2.1-cp313-cp313t-win_arm64.whl", hash = "sha256:225c832a13326e34f212d2072982bb1adb210e0cc0b153e688743018c94a2681", size = 2417234, upload-time = "2025-04-12T17:49:08.399Z" }, +] + +[[package]] +name = "pillow-avif-plugin" +version = "1.5.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/32/a3bfad0537ba6f2accc6a8a2e53e09b266418347f58898f811ca2fb70bd9/pillow_avif_plugin-1.5.2.tar.gz", hash = "sha256:811e0dc8be1e44393d2e3865ec330a8a8a1194b94eb8cfca6fa778e3f476d649", size = 20571, upload-time = "2025-04-24T14:11:49.163Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f8/6a/7a03fd17fe33f07025776d77ee59a67007854a477da89c4d68ab2d8bcc77/pillow_avif_plugin-1.5.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5be8435d2ebf0972f6c2ef69d8869e5875f5cd77c69c9606e0145595b81f7790", size = 3900271, upload-time = "2025-04-24T14:10:45.33Z" }, + { url = "https://files.pythonhosted.org/packages/6c/10/e4daa1c0ad14492724305b4786bad560b8ffd5643e4817d6684f463b7cf0/pillow_avif_plugin-1.5.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d2e571b845da4ea4fc16d647e64656bc754840a10ad5ef9fd020d389ea664c9d", size = 2805824, upload-time = "2025-04-24T14:10:46.489Z" }, + { url = "https://files.pythonhosted.org/packages/58/34/5443fe48d8923c35742e5b11e0ecd2378e4275d6310b6bf7c1533e24cafc/pillow_avif_plugin-1.5.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35d61a9b586793c93e439b9181c201bc34c67cc4817f8f5625b8df37f0a25efe", size = 2991320, upload-time = "2025-04-24T14:10:47.731Z" }, + { url = "https://files.pythonhosted.org/packages/93/9f/a85b96e545a7306743eebae6216a9f5af4869ffa40fd285adead78ebed50/pillow_avif_plugin-1.5.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84fce3d0ef7b5c8ecf5a1a29da487c824b93bf33680de31829e8179bd4511548", size = 6365646, upload-time = "2025-04-24T14:10:48.958Z" }, + { url = "https://files.pythonhosted.org/packages/ec/7e/126fce54561f11d3d4d9ad21a4a14eab2a2cf08ee8668253005c551a15ca/pillow_avif_plugin-1.5.2-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:e0ac45d820bcb895d0667d18a61bf0c940ea4659fcbe991d7ce767ec062c175c", size = 3003952, upload-time = "2025-04-24T14:10:50.218Z" }, + { url = "https://files.pythonhosted.org/packages/f4/62/a7b296c207ff702dcab8508c65c3c0b3a72f61b1967df9a4273cbe68dc76/pillow_avif_plugin-1.5.2-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:8b0c86ade32600b832f2323409239fadd46d17a05380d11836e7fc24e54c170a", size = 4173898, upload-time = "2025-04-24T14:10:51.689Z" }, + { url = "https://files.pythonhosted.org/packages/8f/de/6405c66ce3d3af44b5e0091f26321eb09d8ec75cab4d3d843a316c1686cd/pillow_avif_plugin-1.5.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d639ef381496e0306e43cccd9bf384e0eccba979b6758c2aa4986fb25b920cab", size = 3101313, upload-time = "2025-04-24T14:10:53.143Z" }, + { url = "https://files.pythonhosted.org/packages/8a/de/bee7bd4539d45df2328fb5c52326b72770471aa3441c8b6d91b33e54f7c3/pillow_avif_plugin-1.5.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:3b168757ee646a0b53f58da978b73dc1c5f98da9d36b52908055d54d0a48c845", size = 4195538, upload-time = "2025-04-24T14:10:55.854Z" }, + { url = "https://files.pythonhosted.org/packages/4d/40/f11c63a815bae18b4792df5435e61351d90cc4795da5cb4e19b1d4bf532e/pillow_avif_plugin-1.5.2-cp313-cp313-win_amd64.whl", hash = "sha256:b840a431dbb04f60a18bbd2e28c2b26d845efcddd28f98e9386eb5a5938a3b38", size = 9867834, upload-time = "2025-04-24T14:10:57.26Z" }, + { url = "https://files.pythonhosted.org/packages/f5/ce/36c401834c477fb3034dee6962adacc368f944d72b96f298a2e4787ae44d/pillow_avif_plugin-1.5.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4fb6744377634b28b0ed54fd12a1e6fa6cf09633dc7608958595d2659e1186a8", size = 3900637, upload-time = "2025-04-24T14:10:58.939Z" }, + { url = "https://files.pythonhosted.org/packages/57/e1/faacc26a8da3b1a965860affcc107bc555929bf96a9e7810815aa09ab17f/pillow_avif_plugin-1.5.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:ea00363749cd6c359c054b920fef0cd1f4864af7920c86886339128d704298a3", size = 2806181, upload-time = "2025-04-24T14:11:00.517Z" }, + { url = "https://files.pythonhosted.org/packages/e4/7f/4d92ec39a00308c81b101ad3c8a948aaa3f24d03246e74d68361975f8231/pillow_avif_plugin-1.5.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4b36cce231d6e0fa09972a1558eac18e94a29d83342129488f0a1fcb4509cb8", size = 2996403, upload-time = "2025-04-24T14:11:02.162Z" }, + { url = "https://files.pythonhosted.org/packages/b9/24/a5299390c810daa51932a7c8ba00e14e005199e7fe2474f6701a3890079b/pillow_avif_plugin-1.5.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4053ec0a6767229703d05fd4d47c39b92b6044e14489ed8e79f485c8d96a9ad3", size = 6369881, upload-time = "2025-04-24T14:11:03.55Z" }, + { url = "https://files.pythonhosted.org/packages/53/d7/8ffb730e2321d6493f2facc5e50d4e1364e45ed7315fc711e99ac98ddbd1/pillow_avif_plugin-1.5.2-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:6830b27e41669b9008dc4d9d69f3d66d2ee3d26367b4aa59c229cc5ffc702748", size = 3009137, upload-time = "2025-04-24T14:11:04.841Z" }, + { url = "https://files.pythonhosted.org/packages/8d/df/3df3c4dcb1b30759e27591182afc8ed7533c87591be685fa3fc5ca32bd68/pillow_avif_plugin-1.5.2-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:cf0e32a6a6635de41aabc196a7d888431553e78aae51e25d6602d384ef91be8b", size = 4178359, upload-time = "2025-04-24T14:11:06.05Z" }, + { url = "https://files.pythonhosted.org/packages/36/94/25659c3bc8ae80e856ac012842186200a3a00fb99214dab8ee8049244425/pillow_avif_plugin-1.5.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:bc6bb9a7103b57dcfdea910330323d330220c2e89d71f8182f1dff773f10a12d", size = 3106107, upload-time = "2025-04-24T14:11:07.284Z" }, + { url = "https://files.pythonhosted.org/packages/e9/3a/84bebb05143c7715760c9e51c9a7a579106334167c41f4d6aebfb2966042/pillow_avif_plugin-1.5.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:b54e18be1cf28bacf4da3c132fcf9ae9ff7b5dd6c8f5576dd66f0a099b0d1f7a", size = 4199692, upload-time = "2025-04-24T14:11:08.458Z" }, + { url = "https://files.pythonhosted.org/packages/ca/df/93748424d89bddff2192cf82f34b497dbf73ac2ffd022a481ee74e0aeae8/pillow_avif_plugin-1.5.2-cp313-cp313t-win_amd64.whl", hash = "sha256:981b3205d8389f88e7fccacb25f2c75668a371b8346771cc36bd35cae05560dd", size = 9868519, upload-time = "2025-04-24T14:11:09.852Z" }, +] + [[package]] name = "pluggy" version = "1.6.0"