Skip to content

Commit

Permalink
Merge branch 'v4' into feat/scrapers-config
Browse files Browse the repository at this point in the history
  • Loading branch information
THEGOLDENPRO committed Apr 29, 2024
2 parents 2c13109 + f462c66 commit 8db6af8
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 65 deletions.
2 changes: 1 addition & 1 deletion mov_cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
from .scraper import *
from .download import *

__version__ = "4.3.10"
__version__ = "4.3.14"
27 changes: 9 additions & 18 deletions mov_cli/cli/plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,49 +4,40 @@
if TYPE_CHECKING:
from typing import Tuple, List, Dict, NoReturn

from ..plugins import PluginHookData
from ..plugins import Plugin
PluginsDataT = List[Tuple[str, str, Plugin]]

from devgoldyutils import Colours

from ..plugins import load_plugin
from ..logger import mov_cli_logger

def get_plugins_data(plugins: Dict[str, str]) -> List[Tuple[str, str, PluginHookData]]:
plugins_data: List[Tuple[str, str, PluginHookData]] = []
def get_plugins_data(plugins: Dict[str, str]) -> PluginsDataT:
plugins_data: PluginsDataT = []

for plugin_namespace, plugin_module_name in plugins.items():
plugin = load_plugin(plugin_module_name)

if plugin is None:
continue

plugin_data, _ = plugin

if plugin_data is None:
continue

plugins_data.append(
(plugin_namespace, plugin_module_name, plugin_data, plugin)
(plugin_namespace, plugin_module_name, plugin)
)

return plugins_data

def show_all_plugins(plugins: Dict[str, str]) -> None:

for plugin_namespace, plugin_module_name, plugin_hook_data, plugin in get_plugins_data(plugins):
for plugin_namespace, plugin_module_name, plugin in get_plugins_data(plugins):

if plugin is not None:
plugin_module = plugin[1]

plugin_version = getattr(plugin_module, "__version__", "N/A")
plugin_version = getattr(plugin.module, "__version__", "N/A")

print(f"- {Colours.PURPLE.apply(plugin_module_name)} ({plugin_namespace}) [{Colours.BLUE.apply(plugin_version)}]")

for scraper_name in plugin_hook_data["scrapers"]:
if scraper_name == "DEFAULT":
continue

print(f" - {Colours.PINK_GREY.apply(scraper_name)}")
for scraper_name in plugin.scrapers:
print(f" - {Colours.PINK_GREY.apply(scraper_name[0])}")

def handle_internal_plugin_error(e: Exception) -> NoReturn:
mov_cli_logger.critical(
Expand Down
12 changes: 6 additions & 6 deletions mov_cli/cli/scraper.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from ..config import Config, ScrapersConfigT
from ..utils.episode_selector import EpisodeSelector

from ..plugins import PluginHookData
from .plugins import PluginsDataT
from ..scraper import Scraper, ScraperOptionsT

from devgoldyutils import Colours
Expand Down Expand Up @@ -71,11 +71,11 @@ def select_scraper(plugins: Dict[str, str], scrapers: ScrapersConfigT, fzf_enabl
)

if chosen_plugin is not None:
plugin_namespace, _, plugin_data, plugin = chosen_plugin
plugin_namespace, _, plugin = chosen_plugin

chosen_scraper = prompt(
"Select a scraper",
choices = [scraper for scraper in plugin_data["scrapers"].items()],
choices = [scraper for scraper in plugin.scrapers],
display = lambda x: Colours.BLUE.apply(x[0].lower()),
fzf_enabled = fzf_enabled
)
Expand Down Expand Up @@ -124,7 +124,7 @@ def steal_scraper_args(query: List[str]) -> ScraperOptionsT:

return dict(scraper_options_args)

def get_scraper(scraper_id: str, plugins_data: List[Tuple[str, str, PluginHookData]], user_defined_scrapers: ScrapersConfigT) -> Tuple[str, Type[Scraper] | Tuple[None, List[str]], ScraperOptionsT]:
def get_scraper(scraper_id: str, plugins_data: PluginsDataT, user_defined_scrapers: ScrapersConfigT) -> Tuple[str, Type[Scraper] | Tuple[None, List[str]], ScraperOptionsT]:
scraper_options = {}
available_scrapers = []

Expand All @@ -138,8 +138,8 @@ def get_scraper(scraper_id: str, plugins_data: List[Tuple[str, str, PluginHookDa

platform = what_platform().upper()

for plugin_namespace, _, plugin_hook_data, plugin in plugins_data:
plugin_scrapers = plugin_hook_data["scrapers"]
for plugin_namespace, _, plugin in plugins_data:
plugin_scrapers = plugin.hook_data["scrapers"]

if scraper_id.lower() == plugin_namespace.lower() and f"{platform}.DEFAULT" in plugin_scrapers:
return f"{plugin_namespace}.{platform}.DEFAULT", plugin_scrapers[f"{platform}.DEFAULT"], scraper_options
Expand Down
4 changes: 2 additions & 2 deletions mov_cli/media/media.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ def __init__(

@property
def display_name(self) -> str:
return f"{self.title} ({self.year})"
return f"{self.title} ({self.year})" if self.year is not None else self.title

# Backwards compatibility for post v4.3.0 extensions.
# Backwards compatibility for post v4.3 extensions.
Series = Multi
"""DEPRECATED!!! USE 'Multi' INSTEAD! This will be removed after v4.4."""
Movie = Single
Expand Down
38 changes: 33 additions & 5 deletions mov_cli/plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,20 @@

if TYPE_CHECKING:
from types import ModuleType
from typing import Optional, Dict, Literal, Tuple
from typing import Optional, Dict, Literal, List, Tuple

from .scraper import Scraper

import importlib
from dataclasses import dataclass
from devgoldyutils import LoggerAdapter

from .logger import mov_cli_logger

__all__ = (
"load_plugin",
"PluginHookData"
"PluginHookData",
"Plugin"
)

logger = LoggerAdapter(mov_cli_logger, prefix = "Plugins")
Expand All @@ -29,16 +31,42 @@ class PluginHookData(TypedDict):
"""The name of the pypi package. This is required for the plugin update notifier to work."""
scrapers: Dict[str, Scraper] | Dict[Literal["DEFAULT"], Scraper]

def load_plugin(module_name: str) -> Optional[Tuple[Optional[PluginHookData], ModuleType]]:
@dataclass
class Plugin:
module: ModuleType
hook_data: PluginHookData

@property
def scrapers(self) -> List[Tuple[str, Scraper]]:
non_default_scrapers = []

for scraper_namespace, scraper_class in self.hook_data["scrapers"].items():

if scraper_namespace.endswith("DEFAULT"):
continue

non_default_scrapers.append((scraper_namespace, scraper_class))

return non_default_scrapers

@property
def version(self) -> Optional[str]:
return getattr(self.module, "__version__", None)

def load_plugin(module_name: str) -> Optional[Plugin]:
try:
plugin_module = importlib.import_module(module_name.replace("-", "_"))
except ModuleNotFoundError as e:
logger.error(f"Failed to import a plugin from the module '{module_name}'! Error --> {e}")
return None

plugin_data = getattr(plugin_module, "plugin", None)
plugin_data: PluginHookData = getattr(plugin_module, "plugin", None)

if plugin_data is None:
logger.warning(f"Failed to load the plugin '{module_name}'! It doesn't contain a plugin hook!")
return None

return plugin_data, plugin_module
return Plugin(
module = plugin_module,
hook_data = plugin_data
)
42 changes: 12 additions & 30 deletions mov_cli/utils/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from typing import Tuple, List, Optional, Dict
from typing import Tuple, List, Dict

import httpx
from packaging import version
Expand All @@ -14,8 +14,7 @@

__all__ = (
"update_available",
"plugin_update_available",
"get_plugin_version_hook"
"plugin_update_available"
)

logger = LoggerAdapter(mov_cli_logger, prefix = Colours.GREEN.apply("version"))
Expand Down Expand Up @@ -48,17 +47,21 @@ def plugin_update_available(plugins: Dict[str, str]) -> Tuple[bool, List[str]]:
logger.debug("Checking if plugins need updating...")

for _, module_name in plugins.items():
plugin_version, plugin_hook_data = get_plugin_version_hook(module_name)
plugin = load_plugin(module_name)

if plugin is None:
continue

plugin_version = plugin.version
pypi_package_name = plugin.hook_data.get("package_name", None)

if plugin_version is None:
logger.debug(
f"Skipped update check for '{module_name}' as the plugin " \
"doesn't expose '__version__' in it's root module ('__init__.py')."
f"The plugin '{module_name}' doesn't expose '__version__' in" \
"it's root module ('__init__.py') so it the update checker will skip it."
)
continue

pypi_package_name = plugin_hook_data.get("package_name", None)

if pypi_package_name is None:
logger.debug(
f"Skipped update check for '{module_name}' as the plugin " \
Expand All @@ -85,25 +88,4 @@ def plugin_update_available(plugins: Dict[str, str]) -> Tuple[bool, List[str]]:
if not plugins_with_updates == []:
return True, plugins_with_updates

return False, []

def get_plugin_version_hook(module_name: str):
plugin = load_plugin(module_name)

if plugin is None:
return None, None

plugin_module = plugin[1]
plugin_hook_data = plugin[0]

plugin_version: Optional[str] = getattr(plugin_module, "__version__", None)

if plugin_version is None:
logger.debug(
f"Skipped update check for '{module_name}' as the plugin " \
"doesn't expose '__version__' in it's root module ('__init__.py')."
)

return None, None

return plugin_version, plugin_hook_data
return False, []
6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "mov-cli"
description = "Watch everything from your terminal."
authors = [
{name = "Pain", email = "painedposeidon444@gmail.com"},
{name = "Ananas", email = "ananas@r3tr0ananas.lol"},
{name = "Ananas", email = "ananas@r3tr0ananas.pro"},
{name = "Goldy", email = "goldy@devgoldy.xyz"}
]
readme = {file = "README.md", content-type = "text/markdown"}
Expand All @@ -27,7 +27,7 @@ dependencies = [
"httpx",
"importlib-metadata; python_version<'3.8'",
"toml",
"devgoldyutils>=2.5.7",
"devgoldyutils>=3.0.0beta1",
"typer>=0.12.2",
"inquirer",
"beautifulsoup4",
Expand Down Expand Up @@ -66,4 +66,4 @@ include = ["mov_cli*"]
"mov_cli" = ["config.template.toml", "cli/random_tips.json"]

[project.scripts]
mov-cli = "mov_cli.cli.__main__:app"
mov-cli = "mov_cli.cli.__main__:app"

0 comments on commit 8db6af8

Please sign in to comment.