How to develop a source plugin for nvchecker

Source plugins enable nvchecker to discover software version strings in additional ways.

Where to put the plugins

They are Python modules put in any directories named nvchecker_source in sys.path. This is called namespace packages introduced by PEP 420. For local use, ~/.local/lib/pythonX.Y/site-packages/nvchecker_source is a good place, or you can define the PYTHONPATH environment variable and put nvchecker source plugins there inside a nvchecker_source directory.

Plugins are referenced by their names in the configuration file (source = "xxx"). If multiple plugins have the same name, the first one in sys.path will be used.

How to write a simple plugin

For simple situations, you need to define an async function with the following signature:

async def get_version(
  name: str, conf: Entry, *,
  cache: AsyncCache, keymanager: KeyManager,
  **kwargs,
) -> VersionResult:
  ...

Those types are imported from nvchecker.api.

name is the table keys in the configuration file, and conf is a dict of the content of that table. You should not modify this dict.

cache is an AsyncCache object that caches results for you. Every plugin has its own cache object so that cache keys won’t conflict.

keymanager is a KeyManager object that you can call .get_key(name) to get the key (token) from the keyfile.

There may be additional keyword arguments in the future so **kwargs should be used.

If you want to send an HTTP request, it’s preferred to use :meth: cache.get_json or the :data: nvchecker.api.session object. It will use the auto-selected HTTP backend and handle the proxy option automatically.

For details about these objects, see the API documentation, or take existing source plugins as examples.

How to write a more powerful plugin

You may want more control in your source plugin, e.g. to do batch requests. To do this, you provide a class instead:

class Worker(BaseWorker):
  async def run(self) -> None:
    ...

You will have the following in the attributes:

token_q: Queue[bool],
result_q: Queue[RawResult],
tasks: List[Tuple[str, Entry]],
keymanager: KeyManager,

You are expected to process tasks and put results in result_q. See nvchecker_source/none.py for the simplest example, and nvchecker_source/aur.py for a complete, batching example.

For details about these objects, see the API documentation.

You can also receive a configuration section from the configuration as __config__.source.SOURCE_NAME, where SOURCE_NAME is what your plugin is called. This can be used to specify a mirror site for your plugin to use, e.g. the npm plugin accepts the following config:

[__config__.source.npm]
registry = "https://registry.npm.taobao.org"

When such a configuration exists for your plugin, you need to define a function named configure to receive it:

def configure(config):
  '''use the "config" dict in some way'''
  ...