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

Move build configuration to static configuration files #10958

Merged
merged 5 commits into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 129 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,135 @@
requires = ["setuptools", "wheel", "setuptools-rust"]
build-backend = "setuptools.build_meta"

[project]
name = "qiskit"
description = "An open-source SDK for working with quantum computers at the level of extended quantum circuits, operators, and primitives."
requires-python = ">=3.8"
license = { file = "LICENSE.txt" }
Copy link
Member

Choose a reason for hiding this comment

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

Should we add?

Suggested change
license = { file = "LICENSE.txt" }
license = { file = "LICENSE.txt", text = "Apache 2.0" }

I'm not sure if this is valid syntax or not though. I was doing one final pass through comparing the old setup.py with the metadata in the pyproject.toml and noticed we had the license string set before (and the file was pulled in implicitly I think) but now we just point to the file. But I also need to read PEP 639 to see if this matters at all either.

Copy link
Member Author

Choose a reason for hiding this comment

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

The current PyPA guidelines say it's either-or (though maybe others interpret that text differently), so maybe it's best to just revisit when PEP 639 is accepted?

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, we can look at it again if/when pep 639 is accepted.

authors = [
{ name = "Qiskit Development Team", email = "[email protected]" },
]
keywords = [
"qiskit",
"quantum circuit",
"quantum computing",
"quantum programming language",
Comment on lines +15 to +17
Copy link
Member

Choose a reason for hiding this comment

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

These are good additions. While we're modifying the metadata, did you want anything compiler related here?

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh, I think I just made sure it was synchronised with the tags on the GitHub repo, rather than going out my way to add things. We can add "quantum compiler" to both if you thing it'd be good?

Copy link
Member

Choose a reason for hiding this comment

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

Nah it's fine, we can always tweak these later if needed.

"quantum",
"sdk",
]
classifiers = [
"Environment :: Console",
"Intended Audience :: Developers",
"Intended Audience :: Science/Research",
"License :: OSI Approved :: Apache Software License",
"Operating System :: MacOS",
"Operating System :: Microsoft :: Windows",
"Operating System :: POSIX :: Linux",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
jakelishman marked this conversation as resolved.
Show resolved Hide resolved
"Programming Language :: Python :: 3.12",
"Topic :: Scientific/Engineering",
]
# These are configured in the `tool.setuptools.dynamic` table.
dynamic = ["version", "readme", "dependencies"]

# If modifying this table, be sure to sync with `requirements-optional.txt` and
# `qiskit.utils.optionals`.
[project.optional-dependencies]
qasm3-import = [
"qiskit-qasm3-import >= 0.1.0",
]
visualization = [
"matplotlib >= 3.3",
"ipywidgets >= 7.3.0",
"pydot",
"Pillow >= 4.2.1",
"pylatexenc >= 1.4",
"seaborn >= 0.9.0",
"pygments >= 2.4",
]
crosstalk-pass = [
"z3-solver >= 4.7",
]
csp-layout-pass = [
"python-constraint >= 1.4",
]
# This will make the resolution work for installers from PyPI, but `pip install .[all]` will be
# unreliable because `qiskit` will resolve to the PyPI version, so local changes in the
# optionals won't be reflected.
all = ["qiskit[qasm3-import,visualization,crosstalk-pass,csp-layout-pass]"]
Copy link
Member

Choose a reason for hiding this comment

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

This seems less than ideal, but in practice I guess people aren't using the all extra very frequently. I can't think of a better way to do this besides copy and pasting the component lists for all too. I'm guessing we can't use dynamic for optional dependencies because that's my only other thought.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, it's not super ideal, though I was assuming .[all] isn't being used at all.


[project.urls]
Homepage = "https://qiskit.org"
Documentation = "https://qiskit.org/documentation"
Repository = "https://github.com/Qiskit/qiskit"
Issues = "https://github.com/Qiskit/qiskit/issues"
Changelog = "https://qiskit.org/documentation/release_notes.html"

[project.entry-points."qiskit.unitary_synthesis"]
default = "qiskit.transpiler.passes.synthesis.unitary_synthesis:DefaultUnitarySynthesis"
aqc = "qiskit.transpiler.synthesis.aqc.aqc_plugin:AQCSynthesisPlugin"
sk = "qiskit.transpiler.passes.synthesis.solovay_kitaev_synthesis:SolovayKitaevSynthesis"

[project.entry-points."qiskit.synthesis"]
"clifford.default" = "qiskit.transpiler.passes.synthesis.high_level_synthesis:DefaultSynthesisClifford"
"clifford.ag" = "qiskit.transpiler.passes.synthesis.high_level_synthesis:AGSynthesisClifford"
"clifford.bm" = "qiskit.transpiler.passes.synthesis.high_level_synthesis:BMSynthesisClifford"
"clifford.greedy" = "qiskit.transpiler.passes.synthesis.high_level_synthesis:GreedySynthesisClifford"
"clifford.layers" = "qiskit.transpiler.passes.synthesis.high_level_synthesis:LayerSynthesisClifford"
"clifford.lnn" = "qiskit.transpiler.passes.synthesis.high_level_synthesis:LayerLnnSynthesisClifford"
"linear_function.default" = "qiskit.transpiler.passes.synthesis.high_level_synthesis:DefaultSynthesisLinearFunction"
"linear_function.kms" = "qiskit.transpiler.passes.synthesis.high_level_synthesis:KMSSynthesisLinearFunction"
"linear_function.pmh" = "qiskit.transpiler.passes.synthesis.high_level_synthesis:PMHSynthesisLinearFunction"
"permutation.default" = "qiskit.transpiler.passes.synthesis.high_level_synthesis:BasicSynthesisPermutation"
"permutation.kms" = "qiskit.transpiler.passes.synthesis.high_level_synthesis:KMSSynthesisPermutation"
"permutation.basic" = "qiskit.transpiler.passes.synthesis.high_level_synthesis:BasicSynthesisPermutation"
"permutation.acg" = "qiskit.transpiler.passes.synthesis.high_level_synthesis:ACGSynthesisPermutation"

[project.entry-points."qiskit.transpiler.init"]
default = "qiskit.transpiler.preset_passmanagers.builtin_plugins:DefaultInitPassManager"

[project.entry-points."qiskit.transpiler.translation"]
synthesis = "qiskit.transpiler.preset_passmanagers.builtin_plugins:UnitarySynthesisPassManager"
translator = "qiskit.transpiler.preset_passmanagers.builtin_plugins:BasisTranslatorPassManager"
unroller = "qiskit.transpiler.preset_passmanagers.builtin_plugins:UnrollerPassManager"

[project.entry-points."qiskit.transpiler.routing"]
basic = "qiskit.transpiler.preset_passmanagers.builtin_plugins:BasicSwapPassManager"
lookahead = "qiskit.transpiler.preset_passmanagers.builtin_plugins:LookaheadSwapPassManager"
none = "qiskit.transpiler.preset_passmanagers.builtin_plugins:NoneRoutingPassManager"
sabre = "qiskit.transpiler.preset_passmanagers.builtin_plugins:SabreSwapPassManager"
stochastic = "qiskit.transpiler.preset_passmanagers.builtin_plugins:StochasticSwapPassManager"

[project.entry-points."qiskit.transpiler.optimization"]
default = "qiskit.transpiler.preset_passmanagers.builtin_plugins:OptimizationPassManager"

[project.entry-points."qiskit.transpiler.layout"]
default = "qiskit.transpiler.preset_passmanagers.builtin_plugins:DefaultLayoutPassManager"
dense = "qiskit.transpiler.preset_passmanagers.builtin_plugins:DenseLayoutPassManager"
noise_adaptive = "qiskit.transpiler.preset_passmanagers.builtin_plugins:NoiseAdaptiveLayoutPassManager"
sabre = "qiskit.transpiler.preset_passmanagers.builtin_plugins:SabreLayoutPassManager"
trivial = "qiskit.transpiler.preset_passmanagers.builtin_plugins:TrivialLayoutPassManager"

[project.entry-points."qiskit.transpiler.scheduling"]
alap = "qiskit.transpiler.preset_passmanagers.builtin_plugins:AlapSchedulingPassManager"
asap = "qiskit.transpiler.preset_passmanagers.builtin_plugins:AsapSchedulingPassManager"
default = "qiskit.transpiler.preset_passmanagers.builtin_plugins:DefaultSchedulingPassManager"

[tool.setuptools]
include-package-data = true

[tool.setuptools.dynamic]
version = { file = "qiskit/VERSION.txt" }
readme = { file = "README.md", content-type = "text/markdown" }
dependencies = {file = "requirements.txt" }

[tool.setuptools.packages.find]
include = ["qiskit", "qiskit.*"]
Copy link
Member

Choose a reason for hiding this comment

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

Wouldn't exclude = [""test*"] be more consistent with what we were doing before?

Copy link
Member Author

Choose a reason for hiding this comment

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

It would be more consistent and I can switch it over to that if you prefer. I think the include-list form is maybe a bit less liable to silently break than an exclude list, though.

Copy link
Member

Choose a reason for hiding this comment

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

That's fine with me, this works.


[tool.black]
line-length = 100
target-version = ['py38', 'py39', 'py310', 'py311']
Expand Down
4 changes: 2 additions & 2 deletions qiskit/transpiler/passes/synthesis/high_level_synthesis.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ class HLSConfig:
hls_config = HLSConfig(permutation=[(ACGSynthesisPermutation(), {})])
hls_config = HLSConfig(permutation=[ACGSynthesisPermutation()])

The names of the synthesis algorithms should be declared in ``entry_points`` for
``qiskit.synthesis`` in ``setup.py``, in the form
The names of the synthesis algorithms should be declared in ``entry-points`` table for
``qiskit.synthesis`` in ``pyproject.toml``, in the form
<higher-level-object-name>.<synthesis-method-name>.

The standard higher-level-objects are recommended to have a synthesis method
Expand Down
43 changes: 18 additions & 25 deletions qiskit/transpiler/passes/synthesis/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,18 +130,15 @@ def run(self, unitary, **options):
The second step is to expose the
:class:`~qiskit.transpiler.passes.synthesis.plugin.UnitarySynthesisPlugin` as
a setuptools entry point in the package metadata. This is done by simply adding
an ``entry_points`` entry to the ``setuptools.setup`` call in the ``setup.py``
for the plugin package with the necessary entry points under the
``qiskit.unitary_synthesis`` namespace. For example::

entry_points = {
'qiskit.unitary_synthesis': [
'special = qiskit_plugin_pkg.module.plugin:SpecialUnitarySynthesis',
]
},

(note that the entry point ``name = path`` is a single string not a Python
expression). There isn't a limit to the number of plugins a single package can
an ``entry-points`` table in ``pyproject.toml`` for the plugin package with the necessary entry
points under the ``qiskit.unitary_synthesis`` namespace. For example:

.. code-block:: toml

[project.entry-points."qiskit.unitary-synthesis"]
"special" = "qiskit_plugin_pkg.module.plugin:SpecialUnitarySynthesis"

There isn't a limit to the number of plugins a single package can
include as long as each plugin has a unique name. So a single package can
expose multiple plugins if necessary. The name ``default`` is used by Qiskit
itself and can't be used in a plugin.
Expand Down Expand Up @@ -218,19 +215,15 @@ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **
The second step is to expose the
:class:`~qiskit.transpiler.passes.synthesis.plugin.HighLevelSynthesisPlugin` as
a setuptools entry point in the package metadata. This is done by adding
an ``entry_points`` entry to the ``setuptools.setup`` call in the ``setup.py``
for the plugin package with the necessary entry points under the
``qiskit.synthesis`` namespace. For example::

entry_points = {
'qiskit.synthesis': [
'clifford.special = qiskit_plugin_pkg.module.plugin:SpecialSynthesisClifford',
]
},

(note that the entry point ``name = path`` is a single string not a Python
expression). The ``name`` consists of two parts separated by dot ".": the
name of the
an ``entry-points`` table in ``pyproject.toml`` for the plugin package with the necessary entry
points under the ``qiskit.unitary_synthesis`` namespace. For example:

.. code-block:: toml

[project.entry-points."qiskit.synthesis"]
"clifford.special" = "qiskit_plugin_pkg.module.plugin:SpecialSynthesisClifford"

The ``name`` consists of two parts separated by dot ".": the name of the
type of :class:`~qiskit.circuit.Operation` to which the synthesis plugin applies
(``clifford``), and the name of the plugin (``special``).
There isn't a limit to the number of plugins a single package can
Expand Down
30 changes: 13 additions & 17 deletions qiskit/transpiler/preset_passmanagers/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,23 +134,19 @@ def pass_manager(self, pass_manager_config, optimization_level):
The second step is to expose the :class:`~.PassManagerStagePlugin`
subclass as a setuptools entry point in the package metadata. This can be done
by simply adding an ``entry_points`` entry to the ``setuptools.setup`` call in
the ``setup.py`` or the plugin package with the necessary entry points under the
appropriate namespace for the stage your plugin is for. You can see the list
of stages, entry points, and expectations from the stage in :ref:`stage_table`.
For example, continuing from the example plugin above::
entry_points = {
'qiskit.transpiler.layout': [
'vf2 = qiskit_plugin_pkg.module.plugin:VF2LayoutPlugin',
]
},
Note that the entry point ``name = path`` is a single string not a Python
expression. There isn't a limit to the number of plugins a single package can
include as long as each plugin has a unique name. So a single package can
expose multiple plugins if necessary. Refer to :ref:`stage_table` for a list
of reserved names for each stage.
an ``entry-points`` table in ``pyproject.toml`` for the plugin package with the necessary entry
points under the appropriate namespace for the stage your plugin is for. You can see the list of
stages, entry points, and expectations from the stage in :ref:`stage_table`. For example,
continuing from the example plugin above::
.. code-block:: toml
[project.entry-points."qiskit.transpiler.layout"]
"vf2" = "qiskit_plugin_pkg.module.plugin:VF2LayoutPlugin"
There isn't a limit to the number of plugins a single package can include as long as each plugin has
a unique name. So a single package can expose multiple plugins if necessary. Refer to
:ref:`stage_table` for a list of reserved names for each stage.
Plugin API
==========
Expand Down
2 changes: 1 addition & 1 deletion qiskit/utils/optionals.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@
"""

# NOTE: If you're changing this file, sync it with `requirements-optional.txt` and potentially
# `setup.py` as well.
# `pyproject.toml` as well.

import logging as _logging

Expand Down
2 changes: 1 addition & 1 deletion requirements-optional.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# standard pip conventions, even though none of these are required.
#
# If updating this, you probably want to update `qiskit.utils.optionals` and
# maybe `setup.py` too.
# maybe `pyproject.toml` too.

# Test-runner enhancements.
fixtures
Expand Down
Loading