Simpli - document provider_name property

This commit is contained in:
Nirvana
2026-10-04 12:25:03 +02:00
parent f8793baeff
commit a2b338e05c
2 changed files with 93 additions and 9 deletions
@@ -16,7 +16,7 @@ and fill in the stubs. Read this file first — it explains the contract.
## What you implement
1. **Provider** — `provider.py`. Required. Declares the provider's class
metadata, wires up whatever managers it has, and exposes the public
members, wires up whatever managers it has, and exposes the public
interface.
2. **Auth** — `auth.py`. Optional. Required only if the provider
authenticates requests. Free / static-key providers can omit it
@@ -31,15 +31,51 @@ and fill in the stubs. Read this file first — it explains the contract.
5. **Models** (optional) — `models.py`. Only if you need a custom Channel
or AuthToken subclass.
## Provider class metadata
## Provider class members
Every provider declares these class attributes. They are used by the
registry and the UI before any instance is constructed.
Every provider declares these. Some are abstract (must be implemented by
the concrete class, or the class cannot be instantiated); some are class
attributes with defaults.
PROVIDER_LABEL: ClassVar[str] # display name, e.g. "simpliTV"
PROVIDER_LOGO: ClassVar[str] # logo URL
SUPPORTED_AUTH_TYPES: ClassVar[List[str]] # e.g. ["user_credentials"]
SUPPORTED_COUNTRIES: ClassVar[List[str]] # ALWAYS set this
### Required abstract property
@property
def provider_name(self) -> str: ...
**This is abstract on StreamingProvider.** A subclass that does not
override it cannot be instantiated — Python raises
`TypeError: Can't instantiate abstract class ... with abstract method
provider_name` the moment the registry calls `YourProvider(country=...)`.
The failure is silent if you don't notice it: the registry catches the
exception, logs "Failed to create instance for {name}: ..." at ERROR
level, and moves on. The provider simply does not appear in the UI. If
your provider is registered but never instantiates, this is the first
thing to check.
The value is the provider's machine identifier — lowercase, no spaces,
used in settings keys, log lines, and the `provider` field on models.
It should match the plugin directory name and the `PROVIDER_NAME`
constant in `constants.py`.
@property
def provider_name(self) -> str:
return "your_provider_name"
### Required class attributes
PROVIDER_LABEL: ClassVar[str]
Display name, e.g. "simpliTV". Used by the registry and the UI.
PROVIDER_LOGO: ClassVar[str]
Logo URL.
SUPPORTED_AUTH_TYPES: ClassVar[List[str]]
e.g. ["user_credentials"], ["anonymous"], or ["user_credentials",
"anonymous"] if the provider supports both.
SUPPORTED_COUNTRIES: ClassVar[List[str]]
ALWAYS set this. See "SUPPORTED_COUNTRIES is not optional" below.
### SUPPORTED_COUNTRIES is not optional
@@ -79,6 +115,24 @@ wanting to leave it empty because "I'm not sure yet," declare `["*"]`
instead — it's honest about the ambiguity and behaves correctly in
both the registry and the runtime.
### Cross-check: what the registry reads
The registry's `ProviderMetadata._extract_metadata` reads these members
before any instance exists. If any are missing or wrong, the provider
misbehaves in the UI even if the runtime works.
PROVIDER_LABEL -> metadata.label
PROVIDER_LOGO -> metadata.logo
SUPPORTED_AUTH_TYPES -> metadata.supported_auth_types
SUPPORTED_COUNTRIES -> metadata.supported_countries
class.__name__ -> metadata.plugin_name (derived)
The plugin name is derived from the class name:
`cls.__name__.lower().replace("provider", "")`. `YourProvider` becomes
`your`. If your class name is non-standard the derived name will be
wrong — pick a class name whose lowercase form (minus the word
"provider") matches your intended plugin name.
## The manager ABCs
There are **seven** manager ABCs. **All seven are optional.** A provider
@@ -37,6 +37,36 @@ from .constants import YourConfig
class YourProvider(StreamingProvider):
"""{TODO: provider name} streaming provider."""
# ------------------------------------------------------------------
# provider_name -- ABSTRACT, must be implemented
# ------------------------------------------------------------------
#
# `provider_name` is declared as an @property @abstractmethod on
# StreamingProvider. If this class does not override it, Python
# raises TypeError at instantiation:
#
# Can't instantiate abstract class YourProvider with abstract
# method provider_name
#
# The registry catches that exception, logs it at ERROR level, and
# skips the provider. The symptom is a provider that is registered
# but never appears in the UI.
#
# The value is the machine identifier: lowercase, no spaces, matching
# the plugin directory name and the PROVIDER_NAME constant in
# constants.py. Used in settings keys, log lines, and the `provider`
# field on models.
#
# Do not delete this property. Override the return value; do not
# replace it with a class attribute.
@property
def provider_name(self) -> str:
return "TODO: provider_name"
# ------------------------------------------------------------------
# Class metadata
# ------------------------------------------------------------------
PROVIDER_LABEL: ClassVar[str] = "TODO: display label"
PROVIDER_LOGO: ClassVar[str] = "TODO: logo url"
SUPPORTED_AUTH_TYPES: ClassVar[List[str]] = ["user_credentials"]
@@ -75,7 +105,7 @@ class YourProvider(StreamingProvider):
# 1. HTTP manager.
self.http_manager = self._setup_http_manager(
provider_name="TODO: provider_name",
provider_name=self.provider_name,
proxy_config=proxy_config,
user_agent=self.config.user_agent,
timeout=self.config.timeout,