Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

plugin convenience function for getting the entry point object #9275

Merged
merged 10 commits into from
Apr 18, 2023
36 changes: 35 additions & 1 deletion qiskit/transpiler/preset_passmanagers/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,11 @@ def pass_manager(self, pass_manager_config, optimization_level):
PassManagerStagePlugin
PassManagerStagePluginManager
list_stage_plugins
entry_point_obj
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the docs failure is just because this line needs updating with the new name.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeap.. forgot that. Fixed in 6135d9f

"""

import abc
from typing import List, Optional
from typing import List, Optional, Dict

import stevedore

Expand Down Expand Up @@ -301,3 +302,36 @@ def list_stage_plugins(stage_name: str) -> List[str]:
return plugin_mgr.scheduling_plugins.names()
else:
raise TranspilerError(f"Invalid stage name: {stage_name}")


def passmanager_stage_plugins(stage: str) -> Dict[str, PassManagerStagePlugin]:
"""Return a dict with, for each stage name, the class type of the plugin.

This function is useful for getting more information about a plugin:

from qiskit.transpiler.preset_passmanagers.plugin import passmanager_stage_plugins
routing_plugins = passmanager_stage_plugins('routing')
basic_plugin = routing_plugins['basic']
?basic_plugin
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This ? syntax is specific to IPython - you maybe want to use the standard Python built-in help instead.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 6135d9f


Type: BasicSwapPassManager
String form: <...builtin_plugins.BasicSwapPassManager object at 0xdeadbeef>
File: .../qiskit/transpiler/preset_passmanagers/builtin_plugins.py
Docstring: Plugin class for routing stage with :class:`~.BasicSwap`

Args:
stage: The stage name to get

Returns:
dict: the key is the name of the plugin and the value is the class type for each.

Raises:
TranspilerError: If an invalid stage name is specified.
"""
plugin_mgr = PassManagerStagePluginManager()
try:
manager = getattr(plugin_mgr, f"{stage}_plugins")
except AttributeError as exc:
raise TranspilerError(f"Passmanager stage {stage} not found") from exc

return {name: manager[name].obj for name in manager.names()}
18 changes: 18 additions & 0 deletions releasenotes/notes/entry_point_obj-60625d9d797df1d9.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
features:
- |
The function ``passmanager_stage_plugins`` in the module
``qiskit.transpiler.preset_passmanagers.plugin`` was added to obtain a map between
plugin names and their class type.
This allows to identify and query passmanager plugin documentation. For example::

>>> from qiskit.transpiler.preset_passmanagers.plugin import passmanager_stage_plugins
>>> passmanager_stage_plugins('routing')['lookahead'].__class__
qiskit.transpiler.preset_passmanagers.builtin_plugins.LookaheadSwapPassManager

>>> help(passmanager_stage_plugins('routing')['lookahead'])
Help on BasicSwapPassManager in module qiskit.transpiler.preset_passmanagers.builtin_plugins object:

class BasicSwapPassManager(qiskit.transpiler.preset_passmanagers.plugin.PassManagerStagePlugin)
| Plugin class for routing stage with :class:`~.BasicSwap`
...
12 changes: 12 additions & 0 deletions test/python/transpiler/test_stage_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@
from qiskit.compiler.transpiler import transpile
from qiskit.test import QiskitTestCase
from qiskit.transpiler import PassManager, PassManagerConfig, CouplingMap
from qiskit.transpiler.preset_passmanagers.builtin_plugins import BasicSwapPassManager
from qiskit.transpiler.preset_passmanagers.plugin import (
PassManagerStagePluginManager,
list_stage_plugins,
passmanager_stage_plugins,
)
from qiskit.transpiler.exceptions import TranspilerError
from qiskit.providers.basicaer import QasmSimulatorPy
Expand All @@ -51,6 +53,16 @@ def test_list_stage_plugins_invalid_stage_name(self):
with self.assertRaises(TranspilerError):
list_stage_plugins("not_a_stage")

def test_passmanager_stage_plugins(self):
"""Test entry_point_obj function."""
basic_obj = passmanager_stage_plugins("routing")
self.assertIsInstance(basic_obj["basic"], BasicSwapPassManager)

def test_passmanager_stage_plugins_not_found(self):
"""Test entry_point_obj function with nonexistent stage"""
with self.assertRaises(TranspilerError):
passmanager_stage_plugins("foo_stage")

def test_build_pm_invalid_plugin_name_valid_stage(self):
"""Test get pm from plugin with invalid plugin name and valid stage."""
plugin_manager = PassManagerStagePluginManager()
Expand Down