Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
131 changes: 131 additions & 0 deletions docs/_ext/qpy_version_history.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# This file is derived from Qiskit (https://github.com/Qiskit/qiskit-metapackage)
#
# Original source:
# https://github.com/Qiskit/qiskit-metapackage/blob/0.43.3/docs/versionutils.py
#
# Copyright IBM 2023
# Licensed under the Apache License, Version 2.0

import re
from docutils import nodes
from docutils.parsers.rst import Directive
from docutils.statemachine import ViewList
from sphinx.util.nodes import nested_parse_with_titles
from dulwich.repo import Repo
from packaging import version
from pathlib import Path

from qiskit.qpy.common import QPY_VERSION_HISTORY


def setup(app):
app.add_directive("qpy-version-history", QPYVersionHistory)

class QPYVersionHistory(Directive):
has_content = False

def run(self):
data = self._build_data()
if not data:
return [nodes.paragraph(text="QPY data not found")]
return [self._build_table(data)]

def _get_repo(self):
path = Path(__file__).resolve()
for parent in path.parents:
if (parent / ".git").exists():
return Repo(str(parent))
raise RuntimeError("Repository not found")

def _get_tags(self):
repo = self._get_repo()
tags = []

for ref in repo.refs.keys():
if ref.startswith(b"refs/tags/"):
tag = ref.decode().split("/")[-1]
tags.append(tag)

return tags

def _is_valid_version(self, tag):
return re.fullmatch(r"\d+\.\d+\.\d+", tag)

def _build_data(self):
tags = self._get_tags()
versions = sorted((version.parse(t) for t in tags if self._is_valid_version(t)))
history = sorted(
[(max_, min_, version.parse(first)) for max_, min_, first in QPY_VERSION_HISTORY],
key=lambda x: x[2]
)

def get_qpy_range(cur):
for max_, min_, first in reversed(history):
if cur >= first:
return list(range(min_, max_ + 1))
return None

data = {}
for v in versions:
qpy_range = get_qpy_range(v)
if not qpy_range:
continue

data[str(v)] = {
"dump": qpy_range,
"load": max(qpy_range),
}

return dict(sorted(data.items(), key=lambda x: version.parse(x[0]), reverse=True))

def _build_table(self, data):
table = nodes.table()
table["classes"] += ["colwidths-auto"]
tgroup = nodes.tgroup(cols=3)
table += tgroup

for _ in range(3):
tgroup += nodes.colspec()

thead = nodes.thead()
tbody = nodes.tbody()
tgroup += thead
tgroup += tbody

headers = [
"Qiskit (qiskit-terra for < 1.0.0) version",
":func:`.dump` format(s) output versions",
":func:`.load` maximum supported version (older format versions can always be read)",
]

row = nodes.row()
for h in headers:
entry = nodes.entry()

vl = ViewList()
vl.append(h, "<qpy-version-history>")

node = nodes.paragraph()
nested_parse_with_titles(self.state, vl, node)

entry += node
row += entry

thead += row

for tag, info in data.items():
row = nodes.row()
entry = nodes.entry()
entry += nodes.paragraph(text=tag)
row += entry
entry = nodes.entry()
entry += nodes.paragraph(
text=", ".join(map(str, info["dump"]))
)
row += entry
entry = nodes.entry()
entry += nodes.paragraph(text=str(info["load"]))
row += entry
tbody += row

return table
5 changes: 3 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
import os
import re
from pathlib import Path

import sys
import qiskit

sys.path.insert(0, os.path.abspath("./_ext"))
# pylint: disable=invalid-name,missing-function-docstring,missing-module-docstring


Expand Down Expand Up @@ -50,6 +50,7 @@
"reno.sphinxext",
"sphinxcontrib.katex",
"breathe",
"qpy_version_history",
]

breathe_projects = {"qiskit": "xml/"}
Expand Down
196 changes: 1 addition & 195 deletions qiskit/qpy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,201 +193,7 @@ def open(*args):
Qiskit (and qiskit-terra prior to Qiskit 1.0.0) release going back to the introduction
of QPY in qiskit-terra 0.18.0.

.. list-table:: QPY Format Version History
:header-rows: 1

* - Qiskit (qiskit-terra for < 1.0.0) version
- :func:`.dump` format(s) output versions
- :func:`.load` maximum supported version (older format versions can always be read)
* - 2.4.1
- 13, 14, 15, 16, 17
- 17
* - 2.4.0
- 13, 14, 15, 16, 17
- 17
* - 2.3.1
- 13, 14, 15, 16, 17
- 17
* - 2.3.0
- 13, 14, 15, 16, 17
- 17
* - 2.2.2
- 13, 14, 15, 16
- 16
* - 2.2.1
- 13, 14, 15, 16
- 16
* - 2.2.0
- 13, 14, 15, 16
- 16
* - 2.1.2
- 13, 14, 15, 16
- 16
* - 2.1.1
- 13, 14, 15, 16
- 16
* - 2.1.0
- 13, 14, 15
- 15
* - 2.0.2
- 13, 14
- 14
* - 2.0.1
- 13, 14
- 14
* - 2.0.0
- 13, 14
- 14
* - 1.4.3
- 10, 11, 12, 13
- 13
* - 1.4.2
- 10, 11, 12, 13
- 13
* - 1.4.1
- 10, 11, 12, 13
- 13
* - 1.4.0
- 10, 11, 12, 13
- 13
* - 1.3.3
- 10, 11, 12, 13
- 13
* - 1.3.2
- 10, 11, 12, 13
- 13
* - 1.3.1
- 10, 11, 12, 13
- 13
* - 1.3.0
- 10, 11, 12, 13
- 13
* - 1.2.4
- 10, 11, 12
- 12
* - 1.2.3 (yanked)
- 10, 11, 12
- 12
* - 1.2.2
- 10, 11, 12
- 12
* - 1.2.1
- 10, 11, 12
- 12
* - 1.2.0
- 10, 11, 12
- 12
* - 1.1.0
- 10, 11, 12
- 12
* - 1.0.2
- 10, 11
- 11
* - 1.0.1
- 10, 11
- 11
* - 1.0.0
- 10, 11
- 11
* - 0.46.1
- 10
- 10
* - 0.45.3
- 10
- 10
* - 0.45.2
- 10
- 10
* - 0.45.1
- 10
- 10
* - 0.45.0
- 10
- 10
* - 0.25.3
- 9
- 9
* - 0.25.2
- 9
- 9
* - 0.25.1
- 9
- 9
* - 0.24.2
- 8
- 8
* - 0.24.1
- 7
- 7
* - 0.24.0
- 7
- 7
* - 0.23.3
- 6
- 6
* - 0.23.2
- 6
- 6
* - 0.23.1
- 6
- 6
* - 0.23.0
- 6
- 6
* - 0.22.4
- 5
- 5
* - 0.22.3
- 5
- 5
* - 0.22.2
- 5
- 5
* - 0.22.1
- 5
- 5
* - 0.22.0
- 5
- 5
* - 0.21.2
- 5
- 5
* - 0.21.1
- 5
- 5
* - 0.21.0
- 5
- 5
* - 0.20.2
- 4
- 4
* - 0.20.1
- 4
- 4
* - 0.20.0
- 4
- 4
* - 0.19.2
- 4
- 4
* - 0.19.1
- 3
- 3
* - 0.19.0
- 2
- 2
* - 0.18.3
- 1
- 1
* - 0.18.2
- 1
- 1
* - 0.18.1
- 1
- 1
* - 0.18.0
- 1
- 1
.. qpy-version-history::

.. _qpy_format:

Expand Down
22 changes: 22 additions & 0 deletions qiskit/qpy/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,28 @@
QPY_RUST_WRITE_MIN_VERSION = 17
ENCODE = "utf8"

# only update the points at which either of the two QPY constants change (QPY_VERSION, QPY_COMPATIBILITY_VERSION)
QPY_VERSION_HISTORY = [
# (max_qpy_version, min_qpy_version, release_introduced)
(17, 13, "2.3.0"),
(16, 13, "2.2.0"),
(15, 13, "2.1.0"),
(14, 13, "2.0.0"),
(13, 10, "1.3.0"),
(12, 10, "1.1.0"),
(11, 10, "1.0.0"),
(10, 10, "0.45.0"),
(9, 9, "0.25.0"),
(8, 8, "0.24.2"),
(7, 7, "0.24.0"),
(6, 6, "0.23.0"),
(5, 5, "0.21.0"),
(4, 4, "0.19.2"),
(3, 3, "0.19.1"),
(2, 2, "0.19.0"),
(1, 1, "0.18.0"),
]


def read_generic_typed_data(file_obj):
"""Read a single data chunk from the file like object.
Expand Down