diff --git a/alembic/env.py b/alembic/env.py index e1e69a5..3adba4f 100644 --- a/alembic/env.py +++ b/alembic/env.py @@ -5,9 +5,12 @@ sys.path = ["", ".."] + sys.path[1:] from logging.config import fileConfig # noqa: E402 +from sqlalchemy import ( # noqa: E402 + engine_from_config, + pool, +) + from alembic import context # noqa: E402 -from sqlalchemy import engine_from_config # noqa: E402 -from sqlalchemy import pool # noqa: E402 # this is the Alembic Config object, which provides # access to the values within the .ini file in use. @@ -23,14 +26,20 @@ if config.config_file_name is not None: # from myapp import mymodel # target_metadata = mymodel.Base.metadata -from media_manager.auth.db import User, OAuthAccount # noqa: E402 +from media_manager.auth.db import OAuthAccount, User # noqa: E402 +from media_manager.config import MediaManagerConfig # noqa: E402 +from media_manager.database import Base # noqa: E402 from media_manager.indexer.models import IndexerQueryResult # noqa: E402 -from media_manager.torrent.models import Torrent # noqa: E402 -from media_manager.tv.models import Show, Season, Episode, SeasonFile, SeasonRequest # noqa: E402 from media_manager.movies.models import Movie, MovieFile, MovieRequest # noqa: E402 from media_manager.notification.models import Notification # noqa: E402 -from media_manager.database import Base # noqa: E402 -from media_manager.config import MediaManagerConfig # noqa: E402 +from media_manager.torrent.models import Torrent # noqa: E402 +from media_manager.tv.models import ( # noqa: E402 + Episode, + Season, + SeasonFile, + SeasonRequest, + Show, +) target_metadata = Base.metadata diff --git a/alembic/versions/16e78af9e5bf_add_original_language_columns_to_show_.py b/alembic/versions/16e78af9e5bf_add_original_language_columns_to_show_.py index 6cba8ae..d3283f3 100644 --- a/alembic/versions/16e78af9e5bf_add_original_language_columns_to_show_.py +++ b/alembic/versions/16e78af9e5bf_add_original_language_columns_to_show_.py @@ -8,9 +8,9 @@ Create Date: 2025-12-13 18:47:02.146038 from typing import Sequence, Union -from alembic import op import sqlalchemy as sa +from alembic import op # revision identifiers, used by Alembic. revision: str = "16e78af9e5bf" diff --git a/alembic/versions/1801d9f5a275_add_library_field_to_movie_and_show_.py b/alembic/versions/1801d9f5a275_add_library_field_to_movie_and_show_.py index 4b67e68..a24fb40 100644 --- a/alembic/versions/1801d9f5a275_add_library_field_to_movie_and_show_.py +++ b/alembic/versions/1801d9f5a275_add_library_field_to_movie_and_show_.py @@ -8,9 +8,9 @@ Create Date: 2025-07-16 01:09:44.045395 from typing import Sequence, Union -from alembic import op import sqlalchemy as sa +from alembic import op # revision identifiers, used by Alembic. revision: str = "1801d9f5a275" diff --git a/alembic/versions/1f340754640a_add_continuous_download_column_to_show_.py b/alembic/versions/1f340754640a_add_continuous_download_column_to_show_.py index 44eab02..ac10ba5 100644 --- a/alembic/versions/1f340754640a_add_continuous_download_column_to_show_.py +++ b/alembic/versions/1f340754640a_add_continuous_download_column_to_show_.py @@ -8,9 +8,9 @@ Create Date: 2025-06-22 13:46:01.973406 from typing import Sequence, Union -from alembic import op import sqlalchemy as sa +from alembic import op # revision identifiers, used by Alembic. revision: str = "1f340754640a" diff --git a/alembic/versions/21a19f0675f9_increase_access_token_length.py b/alembic/versions/21a19f0675f9_increase_access_token_length.py index 0c07a18..b2832cc 100644 --- a/alembic/versions/21a19f0675f9_increase_access_token_length.py +++ b/alembic/versions/21a19f0675f9_increase_access_token_length.py @@ -8,9 +8,9 @@ Create Date: 2025-07-06 10:49:08.814496 from typing import Sequence, Union -from alembic import op import sqlalchemy as sa +from alembic import op # revision identifiers, used by Alembic. revision: str = "21a19f0675f9" diff --git a/alembic/versions/2c61f662ca9e_add_imdb_id_fields.py b/alembic/versions/2c61f662ca9e_add_imdb_id_fields.py index 48a61a1..9c4710b 100644 --- a/alembic/versions/2c61f662ca9e_add_imdb_id_fields.py +++ b/alembic/versions/2c61f662ca9e_add_imdb_id_fields.py @@ -8,9 +8,9 @@ Create Date: 2025-12-23 19:42:09.593945 from typing import Sequence, Union -from alembic import op import sqlalchemy as sa +from alembic import op # revision identifiers, used by Alembic. revision: str = "2c61f662ca9e" diff --git a/alembic/versions/333866afcd2c_add_usenet_columns.py b/alembic/versions/333866afcd2c_add_usenet_columns.py index 7728d52..73bb318 100644 --- a/alembic/versions/333866afcd2c_add_usenet_columns.py +++ b/alembic/versions/333866afcd2c_add_usenet_columns.py @@ -8,9 +8,10 @@ Create Date: 2025-07-09 20:55:42.338629 from typing import Sequence, Union -from alembic import op import sqlalchemy as sa +from alembic import op + # revision identifiers, used by Alembic. revision: str = "333866afcd2c" down_revision: Union[str, None] = "aa4689f80796" diff --git a/alembic/versions/5299dfed220b_add_score_field_to_indexerqueryresult_.py b/alembic/versions/5299dfed220b_add_score_field_to_indexerqueryresult_.py index 8a01fcc..1387d0c 100644 --- a/alembic/versions/5299dfed220b_add_score_field_to_indexerqueryresult_.py +++ b/alembic/versions/5299dfed220b_add_score_field_to_indexerqueryresult_.py @@ -8,9 +8,9 @@ Create Date: 2025-07-16 23:24:37.931188 from typing import Sequence, Union -from alembic import op import sqlalchemy as sa +from alembic import op # revision identifiers, used by Alembic. revision: str = "5299dfed220b" diff --git a/alembic/versions/7508237d5bc2_add_ended_column_to_show_table.py b/alembic/versions/7508237d5bc2_add_ended_column_to_show_table.py index 730a9d7..b5c1dfd 100644 --- a/alembic/versions/7508237d5bc2_add_ended_column_to_show_table.py +++ b/alembic/versions/7508237d5bc2_add_ended_column_to_show_table.py @@ -8,9 +8,9 @@ Create Date: 2025-06-10 21:25:27.871064 from typing import Sequence, Union -from alembic import op import sqlalchemy as sa +from alembic import op # revision identifiers, used by Alembic. revision: str = "7508237d5bc2" diff --git a/alembic/versions/93fb07842385_initial_migration.py b/alembic/versions/93fb07842385_initial_migration.py index daea886..7994e77 100644 --- a/alembic/versions/93fb07842385_initial_migration.py +++ b/alembic/versions/93fb07842385_initial_migration.py @@ -8,10 +8,11 @@ Create Date: 2025-05-27 21:36:18.532068 from typing import Sequence, Union -from alembic import op import sqlalchemy as sa from sqlalchemy.dialects import postgresql +from alembic import op + # revision identifiers, used by Alembic. revision: str = "93fb07842385" down_revision: Union[str, None] = None diff --git a/alembic/versions/aa4689f80796_increase_refresh_token_length.py b/alembic/versions/aa4689f80796_increase_refresh_token_length.py index bc928a2..a3f86db 100644 --- a/alembic/versions/aa4689f80796_increase_refresh_token_length.py +++ b/alembic/versions/aa4689f80796_increase_refresh_token_length.py @@ -8,9 +8,9 @@ Create Date: 2025-07-06 10:54:19.714809 from typing import Sequence, Union -from alembic import op import sqlalchemy as sa +from alembic import op # revision identifiers, used by Alembic. revision: str = "aa4689f80796" diff --git a/alembic/versions/eb0bd3cc1852_add_indexer_column_to_indexerqueryresult.py b/alembic/versions/eb0bd3cc1852_add_indexer_column_to_indexerqueryresult.py index 0b1bc82..7d6b1e7 100644 --- a/alembic/versions/eb0bd3cc1852_add_indexer_column_to_indexerqueryresult.py +++ b/alembic/versions/eb0bd3cc1852_add_indexer_column_to_indexerqueryresult.py @@ -8,9 +8,9 @@ Create Date: 2025-10-28 21:39:24.480466 from typing import Sequence, Union -from alembic import op import sqlalchemy as sa +from alembic import op # revision identifiers, used by Alembic. revision: str = "eb0bd3cc1852" diff --git a/media_manager/auth/config.py b/media_manager/auth/config.py index f0ef38d..a664c2b 100644 --- a/media_manager/auth/config.py +++ b/media_manager/auth/config.py @@ -1,7 +1,8 @@ -from pydantic_settings import BaseSettings -from pydantic import Field import secrets +from pydantic import Field +from pydantic_settings import BaseSettings + class OpenIdConfig(BaseSettings): client_id: str = "" diff --git a/media_manager/auth/db.py b/media_manager/auth/db.py index e6bec02..e92a100 100644 --- a/media_manager/auth/db.py +++ b/media_manager/auth/db.py @@ -3,16 +3,16 @@ from typing import Optional from fastapi import Depends from fastapi_users.db import ( + SQLAlchemyBaseOAuthAccountTableUUID, SQLAlchemyBaseUserTableUUID, SQLAlchemyUserDatabase, - SQLAlchemyBaseOAuthAccountTableUUID, ) from sqlalchemy import String from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine -from sqlalchemy.orm import Mapped, relationship, mapped_column +from sqlalchemy.orm import Mapped, mapped_column, relationship -from media_manager.database import Base, build_db_url from media_manager.config import MediaManagerConfig +from media_manager.database import Base, build_db_url class OAuthAccount(SQLAlchemyBaseOAuthAccountTableUUID, Base): diff --git a/media_manager/auth/router.py b/media_manager/auth/router.py index f6beb28..d7ed4d3 100644 --- a/media_manager/auth/router.py +++ b/media_manager/auth/router.py @@ -1,19 +1,18 @@ -from fastapi import APIRouter, Depends -from fastapi import status +from fastapi import APIRouter, Depends, status from fastapi_users.router import get_oauth_router from httpx_oauth.oauth2 import OAuth2 from sqlalchemy import select -from media_manager.config import MediaManagerConfig from media_manager.auth.db import User -from media_manager.auth.schemas import UserRead, AuthMetadata +from media_manager.auth.schemas import AuthMetadata, UserRead from media_manager.auth.users import ( + SECRET, current_superuser, + fastapi_users, openid_client, openid_cookie_auth_backend, - SECRET, - fastapi_users, ) +from media_manager.config import MediaManagerConfig from media_manager.database import DbSessionDependency users_router = APIRouter() diff --git a/media_manager/auth/users.py b/media_manager/auth/users.py index f3e6d0d..62f7c28 100644 --- a/media_manager/auth/users.py +++ b/media_manager/auth/users.py @@ -1,9 +1,10 @@ import contextlib import logging import uuid -from typing import Optional, Any +from typing import Any, Optional from fastapi import Depends, Request +from fastapi.responses import RedirectResponse, Response from fastapi_users import BaseUserManager, FastAPIUsers, UUIDIDMixin, models from fastapi_users.authentication import ( AuthenticationBackend, @@ -13,13 +14,12 @@ from fastapi_users.authentication import ( ) from fastapi_users.db import SQLAlchemyUserDatabase from httpx_oauth.clients.openid import OpenID -from fastapi.responses import RedirectResponse, Response +from sqlalchemy import func, select from starlette import status -from sqlalchemy import select, func import media_manager.notification.utils -from media_manager.auth.db import User, get_user_db, get_async_session -from media_manager.auth.schemas import UserUpdate, UserCreate +from media_manager.auth.db import User, get_async_session, get_user_db +from media_manager.auth.schemas import UserCreate, UserUpdate from media_manager.config import MediaManagerConfig log = logging.getLogger(__name__) diff --git a/media_manager/config.py b/media_manager/config.py index 9457ba4..5c86acf 100644 --- a/media_manager/config.py +++ b/media_manager/config.py @@ -1,13 +1,13 @@ import logging import os from pathlib import Path -from typing import Type, Tuple +from typing import Tuple, Type from pydantic import AnyHttpUrl from pydantic_settings import ( BaseSettings, - SettingsConfigDict, PydanticBaseSettingsSource, + SettingsConfigDict, TomlConfigSettingsSource, ) diff --git a/media_manager/exceptions.py b/media_manager/exceptions.py index 87d9e15..03cb2be 100644 --- a/media_manager/exceptions.py +++ b/media_manager/exceptions.py @@ -1,7 +1,7 @@ from fastapi import Request from fastapi.responses import JSONResponse -from sqlalchemy.exc import IntegrityError from psycopg.errors import UniqueViolation +from sqlalchemy.exc import IntegrityError class MediaManagerException(Exception): diff --git a/media_manager/indexer/dependencies.py b/media_manager/indexer/dependencies.py index 29b763a..b1ae1c1 100644 --- a/media_manager/indexer/dependencies.py +++ b/media_manager/indexer/dependencies.py @@ -2,9 +2,9 @@ from typing import Annotated from fastapi import Depends +from media_manager.database import DbSessionDependency from media_manager.indexer.repository import IndexerRepository from media_manager.indexer.service import IndexerService -from media_manager.database import DbSessionDependency from media_manager.tv.service import TvService diff --git a/media_manager/indexer/indexers/generic.py b/media_manager/indexer/indexers/generic.py index 35ea9ae..f88eeb5 100644 --- a/media_manager/indexer/indexers/generic.py +++ b/media_manager/indexer/indexers/generic.py @@ -1,4 +1,4 @@ -from abc import abstractmethod, ABC +from abc import ABC, abstractmethod from media_manager.indexer.schemas import IndexerQueryResult from media_manager.movies.schemas import Movie diff --git a/media_manager/indexer/indexers/jackett.py b/media_manager/indexer/indexers/jackett.py index 1e01702..2527176 100644 --- a/media_manager/indexer/indexers/jackett.py +++ b/media_manager/indexer/indexers/jackett.py @@ -4,10 +4,10 @@ from concurrent.futures.thread import ThreadPoolExecutor import requests +from media_manager.config import MediaManagerConfig from media_manager.indexer.indexers.generic import GenericIndexer from media_manager.indexer.indexers.torznab_mixin import TorznabMixin from media_manager.indexer.schemas import IndexerQueryResult -from media_manager.config import MediaManagerConfig from media_manager.movies.schemas import Movie from media_manager.tv.schemas import Show diff --git a/media_manager/indexer/indexers/prowlarr.py b/media_manager/indexer/indexers/prowlarr.py index 82e68b7..074d092 100644 --- a/media_manager/indexer/indexers/prowlarr.py +++ b/media_manager/indexer/indexers/prowlarr.py @@ -3,8 +3,8 @@ from dataclasses import dataclass from requests import Session -from media_manager.indexer.indexers.generic import GenericIndexer from media_manager.config import MediaManagerConfig +from media_manager.indexer.indexers.generic import GenericIndexer from media_manager.indexer.indexers.torznab_mixin import TorznabMixin from media_manager.indexer.schemas import IndexerQueryResult from media_manager.movies.schemas import Movie diff --git a/media_manager/indexer/indexers/torznab_mixin.py b/media_manager/indexer/indexers/torznab_mixin.py index 4840c7c..4d7820c 100644 --- a/media_manager/indexer/indexers/torznab_mixin.py +++ b/media_manager/indexer/indexers/torznab_mixin.py @@ -1,9 +1,9 @@ import logging +import xml.etree.ElementTree as ET +from datetime import datetime, timezone +from email.utils import parsedate_to_datetime from media_manager.indexer.schemas import IndexerQueryResult -import xml.etree.ElementTree as ET -from email.utils import parsedate_to_datetime -from datetime import datetime, timezone log = logging.getLogger(__name__) diff --git a/media_manager/indexer/models.py b/media_manager/indexer/models.py index 5c50c75..fea717b 100644 --- a/media_manager/indexer/models.py +++ b/media_manager/indexer/models.py @@ -1,6 +1,6 @@ from uuid import UUID -from sqlalchemy import String, Integer +from sqlalchemy import Integer, String from sqlalchemy.dialects.postgresql import ARRAY from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy.sql.sqltypes import BigInteger diff --git a/media_manager/indexer/repository.py b/media_manager/indexer/repository.py index e10a876..343a6d5 100644 --- a/media_manager/indexer/repository.py +++ b/media_manager/indexer/repository.py @@ -4,9 +4,11 @@ from sqlalchemy.orm import Session from media_manager.indexer.models import IndexerQueryResult from media_manager.indexer.schemas import ( - IndexerQueryResultId, IndexerQueryResult as IndexerQueryResultSchema, ) +from media_manager.indexer.schemas import ( + IndexerQueryResultId, +) log = logging.getLogger(__name__) diff --git a/media_manager/indexer/schemas.py b/media_manager/indexer/schemas.py index fd509fe..4945361 100644 --- a/media_manager/indexer/schemas.py +++ b/media_manager/indexer/schemas.py @@ -3,7 +3,7 @@ import typing from uuid import UUID, uuid4 import pydantic -from pydantic import BaseModel, computed_field, ConfigDict +from pydantic import BaseModel, ConfigDict, computed_field from media_manager.torrent.models import Quality diff --git a/media_manager/indexer/service.py b/media_manager/indexer/service.py index d99c8f9..5100851 100644 --- a/media_manager/indexer/service.py +++ b/media_manager/indexer/service.py @@ -4,8 +4,8 @@ from media_manager.config import MediaManagerConfig from media_manager.indexer.indexers.generic import GenericIndexer from media_manager.indexer.indexers.jackett import Jackett from media_manager.indexer.indexers.prowlarr import Prowlarr -from media_manager.indexer.schemas import IndexerQueryResultId, IndexerQueryResult from media_manager.indexer.repository import IndexerRepository +from media_manager.indexer.schemas import IndexerQueryResult, IndexerQueryResultId from media_manager.movies.schemas import Movie from media_manager.torrent.utils import remove_special_chars_and_parentheses from media_manager.tv.schemas import Show diff --git a/media_manager/logging.py b/media_manager/logging.py index 0b7abc6..0b252c6 100644 --- a/media_manager/logging.py +++ b/media_manager/logging.py @@ -1,10 +1,11 @@ import logging import os import sys -from logging.config import dictConfig -from pythonjsonlogger.json import JsonFormatter -from pathlib import Path from datetime import datetime, timezone +from logging.config import dictConfig +from pathlib import Path + +from pythonjsonlogger.json import JsonFormatter class ISOJsonFormatter(JsonFormatter): diff --git a/media_manager/main.py b/media_manager/main.py index 283b5ee..10c6e39 100644 --- a/media_manager/main.py +++ b/media_manager/main.py @@ -1,43 +1,47 @@ -from media_manager.logging import setup_logging, LOGGING_CONFIG -from media_manager.scheduler import setup_scheduler -from media_manager.filesystem_checks import run_filesystem_checks -from media_manager.config import MediaManagerConfig -import uvicorn +import logging import os -from fastapi import FastAPI, APIRouter + +import uvicorn +from fastapi import APIRouter, FastAPI from fastapi.middleware.cors import CORSMiddleware -from uvicorn.middleware.proxy_headers import ProxyHeadersMiddleware from fastapi.staticfiles import StaticFiles -from starlette.responses import RedirectResponse, FileResponse, Response -from media_manager.auth.users import ( - bearer_auth_backend, - fastapi_users, - cookie_auth_backend, -) +from psycopg.errors import UniqueViolation +from sqlalchemy.exc import IntegrityError +from starlette.responses import FileResponse, RedirectResponse, Response +from uvicorn.middleware.proxy_headers import ProxyHeadersMiddleware + +import media_manager.movies.router as movies_router +import media_manager.torrent.router as torrent_router +import media_manager.tv.router as tv_router from media_manager.auth.router import ( - users_router as custom_users_router, auth_metadata_router, get_openid_router, ) -from media_manager.auth.schemas import UserCreate, UserRead, UserUpdate -from media_manager.exceptions import ( - NotFoundError, - not_found_error_exception_handler, - MediaAlreadyExists, - media_already_exists_exception_handler, - InvalidConfigError, - invalid_config_error_exception_handler, - sqlalchemy_integrity_error_handler, - ConflictError, - conflict_error_handler, +from media_manager.auth.router import ( + users_router as custom_users_router, ) -from sqlalchemy.exc import IntegrityError -from psycopg.errors import UniqueViolation -import media_manager.torrent.router as torrent_router -import media_manager.movies.router as movies_router -import media_manager.tv.router as tv_router +from media_manager.auth.schemas import UserCreate, UserRead, UserUpdate +from media_manager.auth.users import ( + bearer_auth_backend, + cookie_auth_backend, + fastapi_users, +) +from media_manager.config import MediaManagerConfig +from media_manager.exceptions import ( + ConflictError, + InvalidConfigError, + MediaAlreadyExists, + NotFoundError, + conflict_error_handler, + invalid_config_error_exception_handler, + media_already_exists_exception_handler, + not_found_error_exception_handler, + sqlalchemy_integrity_error_handler, +) +from media_manager.filesystem_checks import run_filesystem_checks +from media_manager.logging import LOGGING_CONFIG, setup_logging from media_manager.notification.router import router as notification_router -import logging +from media_manager.scheduler import setup_scheduler setup_logging() diff --git a/media_manager/metadataProvider/abstractMetaDataProvider.py b/media_manager/metadataProvider/abstractMetaDataProvider.py index 471d7b7..1c08c7f 100644 --- a/media_manager/metadataProvider/abstractMetaDataProvider.py +++ b/media_manager/metadataProvider/abstractMetaDataProvider.py @@ -1,10 +1,10 @@ import logging from abc import ABC, abstractmethod -from media_manager.metadataProvider.schemas import MetaDataProviderSearchResult -from media_manager.tv.schemas import Show -from media_manager.movies.schemas import Movie from media_manager.config import MediaManagerConfig +from media_manager.metadataProvider.schemas import MetaDataProviderSearchResult +from media_manager.movies.schemas import Movie +from media_manager.tv.schemas import Show log = logging.getLogger(__name__) diff --git a/media_manager/metadataProvider/dependencies.py b/media_manager/metadataProvider/dependencies.py index bf4cd7b..0cbc16c 100644 --- a/media_manager/metadataProvider/dependencies.py +++ b/media_manager/metadataProvider/dependencies.py @@ -1,12 +1,12 @@ from typing import Annotated, Literal from fastapi import Depends - from fastapi.exceptions import HTTPException -from media_manager.metadataProvider.tmdb import TmdbMetadataProvider + from media_manager.metadataProvider.abstractMetaDataProvider import ( AbstractMetadataProvider, ) +from media_manager.metadataProvider.tmdb import TmdbMetadataProvider from media_manager.metadataProvider.tvdb import TvdbMetadataProvider diff --git a/media_manager/metadataProvider/schemas.py b/media_manager/metadataProvider/schemas.py index 7720df0..98fff7d 100644 --- a/media_manager/metadataProvider/schemas.py +++ b/media_manager/metadataProvider/schemas.py @@ -1,4 +1,5 @@ from pydantic import BaseModel + from media_manager.movies.schemas import MovieId from media_manager.tv.schemas import ShowId diff --git a/media_manager/metadataProvider/tmdb.py b/media_manager/metadataProvider/tmdb.py index 2e59977..81a0896 100644 --- a/media_manager/metadataProvider/tmdb.py +++ b/media_manager/metadataProvider/tmdb.py @@ -8,10 +8,9 @@ from media_manager.metadataProvider.abstractMetaDataProvider import ( AbstractMetadataProvider, ) from media_manager.metadataProvider.schemas import MetaDataProviderSearchResult -from media_manager.tv.schemas import Episode, Season, Show, SeasonNumber, EpisodeNumber from media_manager.movies.schemas import Movie from media_manager.notification.manager import notification_manager - +from media_manager.tv.schemas import Episode, EpisodeNumber, Season, SeasonNumber, Show ENDED_STATUS = {"Ended", "Canceled"} diff --git a/media_manager/metadataProvider/tvdb.py b/media_manager/metadataProvider/tvdb.py index 5198121..d6f9bfe 100644 --- a/media_manager/metadataProvider/tvdb.py +++ b/media_manager/metadataProvider/tvdb.py @@ -1,14 +1,15 @@ -import requests import logging +import requests + import media_manager.metadataProvider.utils from media_manager.config import MediaManagerConfig from media_manager.metadataProvider.abstractMetaDataProvider import ( AbstractMetadataProvider, ) from media_manager.metadataProvider.schemas import MetaDataProviderSearchResult -from media_manager.tv.schemas import Episode, Season, Show, SeasonNumber from media_manager.movies.schemas import Movie +from media_manager.tv.schemas import Episode, Season, SeasonNumber, Show log = logging.getLogger(__name__) diff --git a/media_manager/metadataProvider/utils.py b/media_manager/metadataProvider/utils.py index 4e42c10..c408a2b 100644 --- a/media_manager/metadataProvider/utils.py +++ b/media_manager/metadataProvider/utils.py @@ -1,8 +1,8 @@ from pathlib import Path from uuid import UUID -from PIL import Image import requests +from PIL import Image def get_year_from_date(first_air_date: str | None) -> int | None: diff --git a/media_manager/movies/dependencies.py b/media_manager/movies/dependencies.py index eb25370..33bb786 100644 --- a/media_manager/movies/dependencies.py +++ b/media_manager/movies/dependencies.py @@ -1,16 +1,15 @@ from typing import Annotated -from fastapi import Depends, Path +from fastapi import Depends, HTTPException, Path from media_manager.database import DbSessionDependency +from media_manager.exceptions import NotFoundError +from media_manager.indexer.dependencies import indexer_service_dep from media_manager.movies.repository import MovieRepository from media_manager.movies.schemas import Movie, MovieId from media_manager.movies.service import MovieService -from media_manager.exceptions import NotFoundError -from fastapi import HTTPException -from media_manager.indexer.dependencies import indexer_service_dep -from media_manager.torrent.dependencies import torrent_service_dep from media_manager.notification.dependencies import notification_service_dep +from media_manager.torrent.dependencies import torrent_service_dep def get_movie_repository(db_session: DbSessionDependency) -> MovieRepository: diff --git a/media_manager/movies/repository.py b/media_manager/movies/repository.py index cb59039..053e992 100644 --- a/media_manager/movies/repository.py +++ b/media_manager/movies/repository.py @@ -1,22 +1,33 @@ -from sqlalchemy import select, delete +import logging + +from sqlalchemy import delete, select from sqlalchemy.exc import ( IntegrityError, SQLAlchemyError, ) from sqlalchemy.orm import Session, joinedload -import logging -from media_manager.exceptions import NotFoundError, ConflictError -from media_manager.movies.models import Movie, MovieRequest, MovieFile +from media_manager.exceptions import ConflictError, NotFoundError +from media_manager.movies.models import Movie, MovieFile, MovieRequest from media_manager.movies.schemas import ( Movie as MovieSchema, - MovieId, - MovieRequest as MovieRequestSchema, - MovieRequestId, +) +from media_manager.movies.schemas import ( MovieFile as MovieFileSchema, - RichMovieRequest as RichMovieRequestSchema, +) +from media_manager.movies.schemas import ( + MovieId, + MovieRequestId, +) +from media_manager.movies.schemas import ( + MovieRequest as MovieRequestSchema, +) +from media_manager.movies.schemas import ( MovieTorrent as MovieTorrentSchema, ) +from media_manager.movies.schemas import ( + RichMovieRequest as RichMovieRequestSchema, +) from media_manager.torrent.models import Torrent from media_manager.torrent.schemas import TorrentId diff --git a/media_manager/movies/router.py b/media_manager/movies/router.py index 7b812f3..1ffe82e 100644 --- a/media_manager/movies/router.py +++ b/media_manager/movies/router.py @@ -1,33 +1,33 @@ from pathlib import Path from typing import Annotated -from fastapi import APIRouter, Depends, status, HTTPException +from fastapi import APIRouter, Depends, HTTPException, status from media_manager.auth.schemas import UserRead from media_manager.auth.users import current_active_user, current_superuser from media_manager.config import LibraryItem, MediaManagerConfig from media_manager.exceptions import ConflictError from media_manager.indexer.schemas import ( - IndexerQueryResultId, IndexerQueryResult, + IndexerQueryResultId, ) from media_manager.metadataProvider.dependencies import metadata_provider_dep from media_manager.metadataProvider.schemas import MetaDataProviderSearchResult from media_manager.movies import log from media_manager.movies.dependencies import ( - movie_service_dep, movie_dep, + movie_service_dep, ) from media_manager.movies.schemas import ( + CreateMovieRequest, Movie, MovieRequest, - RichMovieTorrent, + MovieRequestBase, + MovieRequestId, PublicMovie, PublicMovieFile, - CreateMovieRequest, - MovieRequestId, RichMovieRequest, - MovieRequestBase, + RichMovieTorrent, ) from media_manager.schemas import MediaImportSuggestion from media_manager.torrent.schemas import Torrent diff --git a/media_manager/movies/schemas.py b/media_manager/movies/schemas.py index e60e71d..d176be7 100644 --- a/media_manager/movies/schemas.py +++ b/media_manager/movies/schemas.py @@ -2,7 +2,7 @@ import typing import uuid from uuid import UUID -from pydantic import BaseModel, Field, ConfigDict, model_validator +from pydantic import BaseModel, ConfigDict, Field, model_validator from media_manager.auth.schemas import UserRead from media_manager.torrent.models import Quality diff --git a/media_manager/movies/service.py b/media_manager/movies/service.py index adf31bf..b42abcd 100644 --- a/media_manager/movies/service.py +++ b/media_manager/movies/service.py @@ -6,46 +6,49 @@ from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import Session from media_manager.config import MediaManagerConfig +from media_manager.database import SessionLocal, get_session from media_manager.exceptions import InvalidConfigError, NotFoundError from media_manager.indexer.repository import IndexerRepository -from media_manager.database import SessionLocal, get_session -from media_manager.indexer.schemas import IndexerQueryResult -from media_manager.indexer.schemas import IndexerQueryResultId -from media_manager.indexer.utils import evaluate_indexer_query_results -from media_manager.metadataProvider.schemas import MetaDataProviderSearchResult -from media_manager.notification.service import NotificationService -from media_manager.schemas import MediaImportSuggestion -from media_manager.torrent.schemas import Torrent, TorrentStatus, Quality -from media_manager.torrent.service import TorrentService -from media_manager.movies import log -from media_manager.movies.schemas import ( - Movie, - MovieId, - MovieRequest, - MovieFile, - RichMovieTorrent, - PublicMovie, - PublicMovieFile, - MovieRequestId, - RichMovieRequest, -) -from media_manager.torrent.schemas import QualityStrings -from media_manager.movies.repository import MovieRepository -from media_manager.torrent.repository import TorrentRepository -from media_manager.torrent.utils import ( - import_file, - get_files_for_import, - remove_special_characters, - get_importable_media_directories, - remove_special_chars_and_parentheses, - extract_external_id_from_string, -) +from media_manager.indexer.schemas import IndexerQueryResult, IndexerQueryResultId from media_manager.indexer.service import IndexerService +from media_manager.indexer.utils import evaluate_indexer_query_results from media_manager.metadataProvider.abstractMetaDataProvider import ( AbstractMetadataProvider, ) +from media_manager.metadataProvider.schemas import MetaDataProviderSearchResult from media_manager.metadataProvider.tmdb import TmdbMetadataProvider from media_manager.metadataProvider.tvdb import TvdbMetadataProvider +from media_manager.movies import log +from media_manager.movies.repository import MovieRepository +from media_manager.movies.schemas import ( + Movie, + MovieFile, + MovieId, + MovieRequest, + MovieRequestId, + PublicMovie, + PublicMovieFile, + RichMovieRequest, + RichMovieTorrent, +) +from media_manager.notification.service import NotificationService +from media_manager.schemas import MediaImportSuggestion +from media_manager.torrent.repository import TorrentRepository +from media_manager.torrent.schemas import ( + Quality, + QualityStrings, + Torrent, + TorrentStatus, +) +from media_manager.torrent.service import TorrentService +from media_manager.torrent.utils import ( + extract_external_id_from_string, + get_files_for_import, + get_importable_media_directories, + import_file, + remove_special_characters, + remove_special_chars_and_parentheses, +) class MovieService: @@ -158,7 +161,9 @@ class MovieService: ) for movie_torrent in movie_torrents: - torrent = self.torrent_service.get_torrent_by_id(torrent_id=movie_torrent.torrent_id) + torrent = self.torrent_service.get_torrent_by_id( + torrent_id=movie_torrent.torrent_id + ) try: self.torrent_service.cancel_download( torrent=torrent, delete_files=True @@ -684,7 +689,7 @@ class MovieService: movie_id=movie.id, file_path_suffix="IMPORTED", torrent_id=None, - quality=Quality.unknown + quality=Quality.unknown, ) ) diff --git a/media_manager/notification/manager.py b/media_manager/notification/manager.py index 0453297..e254e67 100644 --- a/media_manager/notification/manager.py +++ b/media_manager/notification/manager.py @@ -4,6 +4,8 @@ Notification Manager - Orchestrates sending notifications through all configured import logging from typing import List + +from media_manager.config import MediaManagerConfig from media_manager.notification.schemas import MessageNotification from media_manager.notification.service_providers.abstractNotificationServiceProvider import ( AbstractNotificationServiceProvider, @@ -20,7 +22,6 @@ from media_manager.notification.service_providers.ntfy import ( from media_manager.notification.service_providers.pushover import ( PushoverNotificationServiceProvider, ) -from media_manager.config import MediaManagerConfig logger = logging.getLogger(__name__) diff --git a/media_manager/notification/repository.py b/media_manager/notification/repository.py index ec8ee8e..1ea8ea9 100644 --- a/media_manager/notification/repository.py +++ b/media_manager/notification/repository.py @@ -1,17 +1,20 @@ -from sqlalchemy import select, delete, update +import logging + +from sqlalchemy import delete, select, update from sqlalchemy.exc import ( IntegrityError, SQLAlchemyError, ) from sqlalchemy.orm import Session -import logging -from media_manager.exceptions import NotFoundError, ConflictError +from media_manager.exceptions import ConflictError, NotFoundError from media_manager.notification.models import Notification from media_manager.notification.schemas import ( - NotificationId, Notification as NotificationSchema, ) +from media_manager.notification.schemas import ( + NotificationId, +) log = logging.getLogger(__name__) diff --git a/media_manager/notification/router.py b/media_manager/notification/router.py index 71cdd03..4dd75aa 100644 --- a/media_manager/notification/router.py +++ b/media_manager/notification/router.py @@ -1,8 +1,8 @@ from fastapi import APIRouter, Depends, status from media_manager.auth.users import current_active_user -from media_manager.notification.schemas import Notification, NotificationId from media_manager.notification.dependencies import notification_service_dep +from media_manager.notification.schemas import Notification, NotificationId router = APIRouter() diff --git a/media_manager/notification/schemas.py b/media_manager/notification/schemas.py index d3fe06c..1e3bf8a 100644 --- a/media_manager/notification/schemas.py +++ b/media_manager/notification/schemas.py @@ -3,8 +3,7 @@ import uuid from datetime import datetime from uuid import UUID -from pydantic import BaseModel, Field, ConfigDict - +from pydantic import BaseModel, ConfigDict, Field NotificationId = typing.NewType("NotificationId", UUID) diff --git a/media_manager/notification/service.py b/media_manager/notification/service.py index 211b4af..6d97479 100644 --- a/media_manager/notification/service.py +++ b/media_manager/notification/service.py @@ -1,6 +1,6 @@ -from media_manager.notification.repository import NotificationRepository -from media_manager.notification.schemas import NotificationId, Notification from media_manager.notification.manager import notification_manager +from media_manager.notification.repository import NotificationRepository +from media_manager.notification.schemas import Notification, NotificationId class NotificationService: diff --git a/media_manager/notification/service_providers/abstractNotificationServiceProvider.py b/media_manager/notification/service_providers/abstractNotificationServiceProvider.py index 1bc3ec9..0700c2e 100644 --- a/media_manager/notification/service_providers/abstractNotificationServiceProvider.py +++ b/media_manager/notification/service_providers/abstractNotificationServiceProvider.py @@ -1,4 +1,5 @@ import abc + from media_manager.notification.schemas import MessageNotification diff --git a/media_manager/notification/service_providers/email.py b/media_manager/notification/service_providers/email.py index c52453c..4fc93fc 100644 --- a/media_manager/notification/service_providers/email.py +++ b/media_manager/notification/service_providers/email.py @@ -1,9 +1,9 @@ import media_manager.notification.utils +from media_manager.config import MediaManagerConfig from media_manager.notification.schemas import MessageNotification from media_manager.notification.service_providers.abstractNotificationServiceProvider import ( AbstractNotificationServiceProvider, ) -from media_manager.config import MediaManagerConfig class EmailNotificationServiceProvider(AbstractNotificationServiceProvider): diff --git a/media_manager/scheduler.py b/media_manager/scheduler.py index 52a601f..cd335a6 100644 --- a/media_manager/scheduler.py +++ b/media_manager/scheduler.py @@ -1,17 +1,18 @@ +from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore from apscheduler.schedulers.background import BackgroundScheduler from apscheduler.triggers.cron import CronTrigger -from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore + import media_manager.database +from media_manager.movies.service import ( + auto_download_all_approved_movie_requests, + import_all_movie_torrents, + update_all_movies_metadata, +) from media_manager.tv.service import ( auto_download_all_approved_season_requests, import_all_show_torrents, update_all_non_ended_shows_metadata, ) -from media_manager.movies.service import ( - import_all_movie_torrents, - update_all_movies_metadata, - auto_download_all_approved_movie_requests, -) def setup_scheduler(config, log): diff --git a/media_manager/torrent/dependencies.py b/media_manager/torrent/dependencies.py index 5f01fdf..e8509ce 100644 --- a/media_manager/torrent/dependencies.py +++ b/media_manager/torrent/dependencies.py @@ -1,14 +1,14 @@ from typing import Annotated from fastapi import Depends - -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 -from media_manager.torrent.schemas import TorrentId, Torrent from fastapi.exceptions import HTTPException +from media_manager.database import DbSessionDependency +from media_manager.exceptions import NotFoundError +from media_manager.torrent.repository import TorrentRepository +from media_manager.torrent.schemas import Torrent, TorrentId +from media_manager.torrent.service import TorrentService + def get_torrent_repository(db: DbSessionDependency) -> TorrentRepository: return TorrentRepository(db=db) diff --git a/media_manager/torrent/download_clients/abstractDownloadClient.py b/media_manager/torrent/download_clients/abstractDownloadClient.py index d2d521e..08406a2 100644 --- a/media_manager/torrent/download_clients/abstractDownloadClient.py +++ b/media_manager/torrent/download_clients/abstractDownloadClient.py @@ -1,7 +1,7 @@ from abc import ABC, abstractmethod from media_manager.indexer.schemas import IndexerQueryResult -from media_manager.torrent.schemas import TorrentStatus, Torrent +from media_manager.torrent.schemas import Torrent, TorrentStatus class AbstractDownloadClient(ABC): diff --git a/media_manager/torrent/download_clients/qbittorrent.py b/media_manager/torrent/download_clients/qbittorrent.py index 0bf396e..14e89b4 100644 --- a/media_manager/torrent/download_clients/qbittorrent.py +++ b/media_manager/torrent/download_clients/qbittorrent.py @@ -8,7 +8,7 @@ from media_manager.indexer.schemas import IndexerQueryResult from media_manager.torrent.download_clients.abstractDownloadClient import ( AbstractDownloadClient, ) -from media_manager.torrent.schemas import TorrentStatus, Torrent +from media_manager.torrent.schemas import Torrent, TorrentStatus from media_manager.torrent.utils import get_torrent_hash log = logging.getLogger(__name__) diff --git a/media_manager/torrent/download_clients/sabnzbd.py b/media_manager/torrent/download_clients/sabnzbd.py index 7f785d1..79acafe 100644 --- a/media_manager/torrent/download_clients/sabnzbd.py +++ b/media_manager/torrent/download_clients/sabnzbd.py @@ -1,12 +1,13 @@ import logging +import sabnzbd_api + from media_manager.config import MediaManagerConfig from media_manager.indexer.schemas import IndexerQueryResult from media_manager.torrent.download_clients.abstractDownloadClient import ( AbstractDownloadClient, ) from media_manager.torrent.schemas import Torrent, TorrentStatus -import sabnzbd_api log = logging.getLogger(__name__) diff --git a/media_manager/torrent/download_clients/transmission.py b/media_manager/torrent/download_clients/transmission.py index 7216231..9e8f1ca 100644 --- a/media_manager/torrent/download_clients/transmission.py +++ b/media_manager/torrent/download_clients/transmission.py @@ -1,12 +1,13 @@ import logging import transmission_rpc + from media_manager.config import MediaManagerConfig from media_manager.indexer.schemas import IndexerQueryResult from media_manager.torrent.download_clients.abstractDownloadClient import ( AbstractDownloadClient, ) -from media_manager.torrent.schemas import TorrentStatus, Torrent +from media_manager.torrent.schemas import Torrent, TorrentStatus from media_manager.torrent.utils import get_torrent_hash log = logging.getLogger(__name__) diff --git a/media_manager/torrent/manager.py b/media_manager/torrent/manager.py index c3aedeb..43ee14d 100644 --- a/media_manager/torrent/manager.py +++ b/media_manager/torrent/manager.py @@ -7,10 +7,10 @@ from media_manager.torrent.download_clients.abstractDownloadClient import ( AbstractDownloadClient, ) from media_manager.torrent.download_clients.qbittorrent import QbittorrentDownloadClient +from media_manager.torrent.download_clients.sabnzbd import SabnzbdDownloadClient from media_manager.torrent.download_clients.transmission import ( TransmissionDownloadClient, ) -from media_manager.torrent.download_clients.sabnzbd import SabnzbdDownloadClient from media_manager.torrent.schemas import Torrent, TorrentStatus log = logging.getLogger(__name__) diff --git a/media_manager/torrent/repository.py b/media_manager/torrent/repository.py index 88e2fe7..aba9fc0 100644 --- a/media_manager/torrent/repository.py +++ b/media_manager/torrent/repository.py @@ -1,16 +1,20 @@ -from sqlalchemy import select, delete +from sqlalchemy import delete, select from media_manager.database import DbSessionDependency -from media_manager.torrent.models import Torrent -from media_manager.torrent.schemas import TorrentId, Torrent as TorrentSchema -from media_manager.tv.models import SeasonFile, Show, Season -from media_manager.tv.schemas import SeasonFile as SeasonFileSchema, Show as ShowSchema from media_manager.exceptions import NotFoundError from media_manager.movies.models import Movie, MovieFile from media_manager.movies.schemas import ( Movie as MovieSchema, +) +from media_manager.movies.schemas import ( MovieFile as MovieFileSchema, ) +from media_manager.torrent.models import Torrent +from media_manager.torrent.schemas import Torrent as TorrentSchema +from media_manager.torrent.schemas import TorrentId +from media_manager.tv.models import Season, SeasonFile, Show +from media_manager.tv.schemas import SeasonFile as SeasonFileSchema +from media_manager.tv.schemas import Show as ShowSchema class TorrentRepository: diff --git a/media_manager/torrent/router.py b/media_manager/torrent/router.py index 3835825..abb03c3 100644 --- a/media_manager/torrent/router.py +++ b/media_manager/torrent/router.py @@ -1,14 +1,12 @@ +from fastapi import APIRouter, status from fastapi.exceptions import HTTPException - -from fastapi import APIRouter -from fastapi import status from fastapi.params import Depends from media_manager.auth.users import current_active_user, current_superuser from media_manager.torrent.dependencies import ( - torrent_service_dep, torrent_dep, torrent_repository_dep, + torrent_service_dep, ) from media_manager.torrent.schemas import Torrent, TorrentStatus diff --git a/media_manager/torrent/schemas.py b/media_manager/torrent/schemas.py index dfcca71..a481602 100644 --- a/media_manager/torrent/schemas.py +++ b/media_manager/torrent/schemas.py @@ -2,7 +2,7 @@ import typing import uuid from enum import Enum -from pydantic import ConfigDict, BaseModel, Field +from pydantic import BaseModel, ConfigDict, Field TorrentId = typing.NewType("TorrentId", uuid.UUID) diff --git a/media_manager/torrent/service.py b/media_manager/torrent/service.py index 6181fdf..f27eaf9 100644 --- a/media_manager/torrent/service.py +++ b/media_manager/torrent/service.py @@ -1,11 +1,11 @@ import logging from media_manager.indexer.schemas import IndexerQueryResult +from media_manager.movies.schemas import Movie from media_manager.torrent.manager import DownloadManager from media_manager.torrent.repository import TorrentRepository from media_manager.torrent.schemas import Torrent, TorrentId from media_manager.tv.schemas import SeasonFile, Show -from media_manager.movies.schemas import Movie log = logging.getLogger(__name__) diff --git a/media_manager/torrent/utils.py b/media_manager/torrent/utils.py index a3a614b..9352f6b 100644 --- a/media_manager/torrent/utils.py +++ b/media_manager/torrent/utils.py @@ -2,13 +2,13 @@ import hashlib import logging import mimetypes import re -from pathlib import Path, UnsupportedOperation import shutil +from pathlib import Path, UnsupportedOperation import bencoder +import libtorrent import patoolib import requests -import libtorrent from requests.exceptions import InvalidSchema from media_manager.config import MediaManagerConfig diff --git a/media_manager/tv/dependencies.py b/media_manager/tv/dependencies.py index 5285982..421bf24 100644 --- a/media_manager/tv/dependencies.py +++ b/media_manager/tv/dependencies.py @@ -1,16 +1,15 @@ from typing import Annotated -from fastapi import Depends, Path +from fastapi import Depends, HTTPException, Path from media_manager.database import DbSessionDependency -from media_manager.tv.repository import TvRepository -from media_manager.tv.schemas import Show, ShowId, SeasonId, Season -from media_manager.tv.service import TvService from media_manager.exceptions import NotFoundError -from fastapi import HTTPException from media_manager.indexer.dependencies import indexer_service_dep -from media_manager.torrent.dependencies import torrent_service_dep from media_manager.notification.dependencies import notification_service_dep +from media_manager.torrent.dependencies import torrent_service_dep +from media_manager.tv.repository import TvRepository +from media_manager.tv.schemas import Season, SeasonId, Show, ShowId +from media_manager.tv.service import TvService def get_tv_repository(db_session: DbSessionDependency) -> TvRepository: diff --git a/media_manager/tv/repository.py b/media_manager/tv/repository.py index f7d534d..c9b0b50 100644 --- a/media_manager/tv/repository.py +++ b/media_manager/tv/repository.py @@ -1,27 +1,40 @@ -from sqlalchemy import select, delete, func +from sqlalchemy import delete, func, select from sqlalchemy.exc import ( IntegrityError, SQLAlchemyError, ) from sqlalchemy.orm import Session, joinedload +from media_manager.exceptions import ConflictError, NotFoundError from media_manager.torrent.models import Torrent -from media_manager.torrent.schemas import TorrentId, Torrent as TorrentSchema +from media_manager.torrent.schemas import Torrent as TorrentSchema +from media_manager.torrent.schemas import TorrentId from media_manager.tv import log -from media_manager.tv.models import Season, Show, Episode, SeasonRequest, SeasonFile -from media_manager.exceptions import NotFoundError, ConflictError +from media_manager.tv.models import Episode, Season, SeasonFile, SeasonRequest, Show from media_manager.tv.schemas import ( - Season as SeasonSchema, - SeasonId, - Show as ShowSchema, - ShowId, Episode as EpisodeSchema, - SeasonRequest as SeasonRequestSchema, - SeasonFile as SeasonFileSchema, +) +from media_manager.tv.schemas import ( + EpisodeId, + SeasonId, SeasonNumber, SeasonRequestId, + ShowId, +) +from media_manager.tv.schemas import ( RichSeasonRequest as RichSeasonRequestSchema, - EpisodeId, +) +from media_manager.tv.schemas import ( + Season as SeasonSchema, +) +from media_manager.tv.schemas import ( + SeasonFile as SeasonFileSchema, +) +from media_manager.tv.schemas import ( + SeasonRequest as SeasonRequestSchema, +) +from media_manager.tv.schemas import ( + Show as ShowSchema, ) diff --git a/media_manager/tv/router.py b/media_manager/tv/router.py index 137c664..e9b50ad 100644 --- a/media_manager/tv/router.py +++ b/media_manager/tv/router.py @@ -1,16 +1,16 @@ from pathlib import Path from typing import Annotated -from fastapi import APIRouter, Depends, status, HTTPException +from fastapi import APIRouter, Depends, HTTPException, status from media_manager.auth.db import User from media_manager.auth.schemas import UserRead from media_manager.auth.users import current_active_user, current_superuser -from media_manager.config import MediaManagerConfig, LibraryItem +from media_manager.config import LibraryItem, MediaManagerConfig from media_manager.exceptions import MediaAlreadyExists from media_manager.indexer.schemas import ( - IndexerQueryResultId, IndexerQueryResult, + IndexerQueryResultId, ) from media_manager.metadataProvider.dependencies import metadata_provider_dep from media_manager.metadataProvider.schemas import MetaDataProviderSearchResult @@ -24,17 +24,17 @@ from media_manager.tv.dependencies import ( tv_service_dep, ) from media_manager.tv.schemas import ( - Show, - SeasonRequest, - ShowId, - RichShowTorrent, - PublicShow, - PublicSeasonFile, CreateSeasonRequest, - SeasonRequestId, - UpdateSeasonRequest, + PublicSeasonFile, + PublicShow, RichSeasonRequest, + RichShowTorrent, Season, + SeasonRequest, + SeasonRequestId, + Show, + ShowId, + UpdateSeasonRequest, ) router = APIRouter() diff --git a/media_manager/tv/schemas.py b/media_manager/tv/schemas.py index 2c76e09..d40ea3f 100644 --- a/media_manager/tv/schemas.py +++ b/media_manager/tv/schemas.py @@ -2,7 +2,7 @@ import typing import uuid from uuid import UUID -from pydantic import BaseModel, Field, ConfigDict, model_validator +from pydantic import BaseModel, ConfigDict, Field, model_validator from media_manager.auth.schemas import UserRead from media_manager.torrent.models import Quality diff --git a/media_manager/tv/service.py b/media_manager/tv/service.py index 3b04645..71c56b6 100644 --- a/media_manager/tv/service.py +++ b/media_manager/tv/service.py @@ -1,58 +1,62 @@ +import pprint import re import shutil +from pathlib import Path from sqlalchemy.exc import IntegrityError from media_manager.config import MediaManagerConfig from media_manager.database import get_session -from media_manager.exceptions import InvalidConfigError +from media_manager.exceptions import InvalidConfigError, NotFoundError from media_manager.indexer.repository import IndexerRepository -from media_manager.indexer.schemas import IndexerQueryResult -from media_manager.indexer.schemas import IndexerQueryResultId -from media_manager.indexer.utils import evaluate_indexer_query_results -from media_manager.metadataProvider.schemas import MetaDataProviderSearchResult -from media_manager.notification.service import NotificationService -from media_manager.torrent.schemas import Torrent, TorrentStatus, Quality -from media_manager.torrent.service import TorrentService -from media_manager.tv import log -from media_manager.tv.schemas import ( - Show, - ShowId, - SeasonRequest, - SeasonFile, - SeasonId, - Season, - RichShowTorrent, - RichSeasonTorrent, - PublicSeason, - PublicShow, - PublicSeasonFile, - SeasonRequestId, - RichSeasonRequest, - EpisodeId, - Episode as EpisodeSchema, -) -from media_manager.torrent.schemas import QualityStrings -from media_manager.tv.repository import TvRepository -from media_manager.exceptions import NotFoundError -import pprint -from pathlib import Path -from media_manager.torrent.repository import TorrentRepository -from media_manager.torrent.utils import ( - import_file, - get_files_for_import, - remove_special_characters, - get_importable_media_directories, - extract_external_id_from_string, - remove_special_chars_and_parentheses, -) +from media_manager.indexer.schemas import IndexerQueryResult, IndexerQueryResultId from media_manager.indexer.service import IndexerService +from media_manager.indexer.utils import evaluate_indexer_query_results from media_manager.metadataProvider.abstractMetaDataProvider import ( AbstractMetadataProvider, ) +from media_manager.metadataProvider.schemas import MetaDataProviderSearchResult from media_manager.metadataProvider.tmdb import TmdbMetadataProvider from media_manager.metadataProvider.tvdb import TvdbMetadataProvider +from media_manager.notification.service import NotificationService from media_manager.schemas import MediaImportSuggestion +from media_manager.torrent.repository import TorrentRepository +from media_manager.torrent.schemas import ( + Quality, + QualityStrings, + Torrent, + TorrentStatus, +) +from media_manager.torrent.service import TorrentService +from media_manager.torrent.utils import ( + extract_external_id_from_string, + get_files_for_import, + get_importable_media_directories, + import_file, + remove_special_characters, + remove_special_chars_and_parentheses, +) +from media_manager.tv import log +from media_manager.tv.repository import TvRepository +from media_manager.tv.schemas import ( + Episode as EpisodeSchema, +) +from media_manager.tv.schemas import ( + EpisodeId, + PublicSeason, + PublicSeasonFile, + PublicShow, + RichSeasonRequest, + RichSeasonTorrent, + RichShowTorrent, + Season, + SeasonFile, + SeasonId, + SeasonRequest, + SeasonRequestId, + Show, + ShowId, +) class TvService: diff --git a/metadata_relay/app/tmdb.py b/metadata_relay/app/tmdb.py index 22288be..45660f5 100644 --- a/metadata_relay/app/tmdb.py +++ b/metadata_relay/app/tmdb.py @@ -2,8 +2,8 @@ import logging import os import tmdbsimple -from tmdbsimple import TV, TV_Seasons, Movies, Trending, Search from fastapi import APIRouter +from tmdbsimple import TV, Movies, Search, Trending, TV_Seasons log = logging.getLogger(__name__) diff --git a/metadata_relay/app/tvdb.py b/metadata_relay/app/tvdb.py index 0014786..4f62b82 100644 --- a/metadata_relay/app/tvdb.py +++ b/metadata_relay/app/tvdb.py @@ -1,7 +1,7 @@ +import logging import os import tvdb_v4_official -import logging from fastapi import APIRouter log = logging.getLogger(__name__) diff --git a/metadata_relay/main.py b/metadata_relay/main.py index 6d42ae1..cac996f 100644 --- a/metadata_relay/main.py +++ b/metadata_relay/main.py @@ -1,9 +1,9 @@ import os -from fastapi import FastAPI -from starlette_exporter import PrometheusMiddleware, handle_metrics from app.tmdb import router as tmdb_router from app.tvdb import router as tvdb_router +from fastapi import FastAPI +from starlette_exporter import PrometheusMiddleware, handle_metrics print("Hello world!") app = FastAPI(root_path=os.getenv("BASE_PATH")) diff --git a/ruff.toml b/ruff.toml index 8e5b53f..de0a5e4 100644 --- a/ruff.toml +++ b/ruff.toml @@ -10,7 +10,7 @@ extend-select = [ "C4", "COM", "E", "EM", "EXE", "F", "FA", "FAST", "FIX", "FLY", "FURB", - "ICN", "ISC", + "I", "ICN", "ISC", "LOG", "PGH", "PT", "PYI", "Q",