class_docstr: Core class which manages registration of plugin objects and 1:N hook
  calling.
  
  You can register new hooks by calling :meth:`add_hookspecs(module_or_class)
  <PluginManager.add_hookspecs>`.
  
  You can register plugin objects (which contain hook implementations) by
  calling :meth:`register(plugin) <PluginManager.register>`.
  
  For debugging purposes you can call :meth:`PluginManager.enable_tracing`
  which will subsequently send debug information to the trace helper.
  
  :param project_name:
      The short project name. Prefer snake case. Make sure it's unique!
docstr: Register a plugin and return its name.
  
  :param name:
      The name under which to register the plugin. If not specified, a
      name is generated using :func:`get_canonical_name`.
  
  :returns:
      The plugin name. If the name is blocked from registering, returns
      ``None``.
  
  If the plugin is already registered, raises a :exc:`ValueError`.
docstr_tok: ["Register","a","plugin","and","return","its","name",".",":","param","name",":","The","name","under","which","to","register","the","plugin",".","If","not","specified",",","a","name","is","generated","using",":","func",":","`","get_canonical_name","`",".",":","returns",":","The","plugin","name",".","If","the","name","is","blocked","from","registering",",","returns","``","None","``",".","If","the","plugin","is","already","registered",",","raises","a",":","exc",":","`","ValueError","`","."]
code: def register(
      self, plugin: _Plugin, name: str | None = None
  ) -> str | None:
      """Register a plugin and return its name.
  
      :param name:
          The name under which to register the plugin. If not specified, a
          name is generated using :func:`get_canonical_name`.
  
      :returns:
          The plugin name. If the name is blocked from registering, returns
          ``None``.
  
      If the plugin is already registered, raises a :exc:`ValueError`.
      """
      plugin_name = name or self.get_canonical_name(plugin)
  
      if plugin_name in self._name2plugin:
          if self._name2plugin.get(plugin_name, -1) is None:
              return None  # blocked plugin, return None to indicate no registration
          raise ValueError(
              "Plugin name already registered: %s=%s\n%s"
              % (plugin_name, plugin, self._name2plugin)
          )
  
      if plugin in self._name2plugin.values():
          raise ValueError(
              "Plugin already registered under a different name: %s=%s\n%s"
              % (plugin_name, plugin, self._name2plugin)
          )
  
      # XXX if an error happens we should make sure no state has been
      # changed at point of return
      self._name2plugin[plugin_name] = plugin
  
      # register matching hook implementations of the plugin
      for name in dir(plugin):
          hookimpl_opts = self.parse_hookimpl_opts(plugin, name)
          if hookimpl_opts is not None:
              normalize_hookimpl_opts(hookimpl_opts)
              method: _HookImplFunction[object] = getattr(plugin, name)
              hookimpl = HookImpl(
                  plugin, plugin_name, method, hookimpl_opts
              )
              name = hookimpl_opts.get("specname") or name
              hook: HookCaller | None = getattr(self.hook, name, None)
              if hook is None:
                  hook = HookCaller(name, self._hookexec)
                  setattr(self.hook, name, hook)
              elif hook.has_spec():
                  self._verify_hook(hook, hookimpl)
                  hook._maybe_apply_history(hookimpl)
              hook._add_hookimpl(hookimpl)
      return plugin_name
  
imports: from __future__ import annotations
  import importlib.metadata
  import inspect
  import types
  import warnings
  from typing import Any
  from typing import Callable
  from typing import cast
  from typing import Final
  from typing import Iterable
  from typing import Mapping
  from typing import Sequence
  from .None import _tracing
  from ._callers import _multicall
  from ._hooks import _HookImplFunction
  from ._hooks import _Namespace
  from ._hooks import _Plugin
  from ._hooks import _SubsetHookCaller
  from ._hooks import HookCaller
  from ._hooks import HookImpl
  from ._hooks import HookimplOpts
  from ._hooks import HookRelay
  from ._hooks import HookspecOpts
  from ._hooks import normalize_hookimpl_opts
  from ._result import Result
label_desc: Use image node_id 3 for calling the PluginManager obj's underlying member method code with example usage: obj.register(plugin, name) and returns: plugin_name, None