diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 249732b..641603f 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -28,6 +28,7 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: '0' + submodules: true - run: git fetch --depth=1 origin +refs/tags/*:refs/tags/* +refs/heads/*:refs/remotes/origin/* - name: Set up Python 3.10 if: github.event_name == 'push' || github.event_name == 'schedule' @@ -68,15 +69,20 @@ jobs: with: name: artefact-${{ matrix.os }} path: wheelhouse/ + - name: install poetry + run: pip install poetry - name: Install docs dependencies if: (matrix.os == 'ubuntu-22.04') && (github.event_name == 'pull_request' || github.event_name == 'schedule' ) run: | - pip install -r .github/workflows/docs/requirements.txt + cd docs + bash ./install.sh + for w in `find wheelhouse/ -type f -name "*.whl"` ; do poetry install $w ; done - name: Build docs if: (matrix.os == 'ubuntu-22.04') && (github.event_name == 'pull_request' || github.event_name == 'schedule' ) timeout-minutes: 20 run: | - ./.github/workflows/docs/check-build-docs + cd docs + poetry run bash ./build-docs.sh publish_to_pypi: @@ -113,24 +119,27 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: '0' - - name: Set up Python 3.10 + submodules: true + - name: Set up Python 3.11 uses: actions/setup-python@v5 with: - python-version: '3.10' + python-version: '3.11' - name: Download all wheels uses: actions/download-artifact@v4 with: path: wheelhouse - name: Install pip, wheel run: pip install -U pip wheel + - name: Install poetry + run: pip install poetry - name: Install extension - run: for w in `find wheelhouse/ -type f -name "*.whl"` ; do pip install $w ; done + run: for w in `find wheelhouse/ -type f -name "*.whl"` ; do poetry install $w ; done - name: Install docs dependencies run: | - pip install -r .github/workflows/docs/requirements.txt + cd docs + bash ./install.sh - name: Build docs timeout-minutes: 20 run: | - cd .github/workflows/docs - mkdir extensions - ./build-docs -d ${GITHUB_WORKSPACE}/.github/workflows/docs/extensions/api + cd docs + poetry run bash ./build-docs.sh diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 4ace326..813487a 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -1,4 +1,4 @@ -name: Pytket ProjectQ Docs +name: Build docs on: push: @@ -7,30 +7,27 @@ on: schedule: # 04:00 every Tuesday morning - cron: '0 4 * * 2' + jobs: docs: name: build docs runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - - name: Set up Python 3.10 + with: + submodules: true + - name: Set up Python 3.11 uses: actions/setup-python@v5 with: - python-version: '3.10' - - name: Upgrade pip and install wheel - run: pip install --upgrade pip wheel - - name: Install pytket projectq - run: pip install . + python-version: '3.11' + - name: install poetry + run: pip install poetry - name: Install docs dependencies - run: | - pip install -r .github/workflows/docs/requirements.txt + run: cd docs && bash install.sh + - name: Install pytket projectq + run: cd docs && poetry run pip install ../. - name: Test building docs - timeout-minutes: 20 + timeout-minutes: 10 run: | - cd .github/workflows/docs - mkdir extensions - ./build-docs -d ${GITHUB_WORKSPACE}/.github/workflows/docs/extensions - - uses: actions/upload-artifact@v4 - with: - name: pytket-extension-docs - path: .github/workflows/docs/extensions/ + cd docs + poetry run bash build-docs.sh \ No newline at end of file diff --git a/.github/workflows/docs/Quantinuum_logo_black.png b/.github/workflows/docs/Quantinuum_logo_black.png deleted file mode 100644 index 5569581..0000000 Binary files a/.github/workflows/docs/Quantinuum_logo_black.png and /dev/null differ diff --git a/.github/workflows/docs/Quantinuum_logo_white.png b/.github/workflows/docs/Quantinuum_logo_white.png deleted file mode 100644 index e896db9..0000000 Binary files a/.github/workflows/docs/Quantinuum_logo_white.png and /dev/null differ diff --git a/.github/workflows/docs/build-docs b/.github/workflows/docs/build-docs deleted file mode 100755 index 1bae76c..0000000 --- a/.github/workflows/docs/build-docs +++ /dev/null @@ -1,112 +0,0 @@ -#!/usr/bin/env python - -import argparse -import datetime -from importlib import import_module -from pathlib import Path -import shutil -import subprocess -import sys - -DOCS_DIR = Path(sys.argv[0]).absolute().parent -MODULES_DIR = DOCS_DIR.parent.parent.parent -TKET_EXAMPLES_LINK = "https://tket.quantinuum.com/examples/" -TKET_MANUAL_LINK = "https://tket.quantinuum.com/user-manual/" -TKET_WEBSITE_LINK = "https://tket.quantinuum.com/" -PYTKET_DOCS_LINK = "https://tket.quantinuum.com/api-docs/" -PYTKET_EX_DOCS_LINK = "https://tket.quantinuum.com/api-docs/extensions.html" -PYTKET_PROJECTQ_PYPI_LINK = "https://pypi.org/project/pytket-projectq/" -PYTKET_PROJECTQ_GITHUB = "https://github.com/CQCL/pytket-projectq" -MODULE = "projectq" - -def get_module_version(): - m = import_module(f"pytket.extensions.{MODULE}") - return m._metadata.__extension_version__.split(".") - - -def remove_dir(dirpath): - if dirpath.exists() and dirpath.is_dir(): - shutil.rmtree(dirpath) - - -def fix_links(filepath): - with open(filepath, "r", encoding="utf8") as f: - content = f.read() - content = content.replace("pytket._tket", "pytket") - with open(filepath, "w", encoding="utf8") as f: - f.write(content) - - -def build_module_docs(): - v = get_module_version() - mod_docs = MODULES_DIR / "docs" - mod_build = mod_docs / "build" - conf_copy = mod_docs / "conf.py" - logo_copy_black = mod_docs / "Quantinuum_logo_black.png" - logo_copy_white = mod_docs / "Quantinuum_logo_white.png" - shutil.copy(DOCS_DIR / "conf.py", conf_copy) - shutil.copy(DOCS_DIR / "Quantinuum_logo_black.png", logo_copy_black) - shutil.copy(DOCS_DIR / "Quantinuum_logo_white.png", logo_copy_white) - remove_dir(mod_build) - index_rst = mod_docs / "index.rst" - with open(mod_docs / "intro.txt", "r") as f: - content = f.readlines() - content.append( - "\n.. toctree::\n\t:caption: pytket documentation:\n\t:maxdepth: 1\n\n" - ) - content.append(f"\tpytket API docs <{PYTKET_DOCS_LINK}>\n") - content.append(f"\tpytket extensions <{PYTKET_EX_DOCS_LINK}>\n") - content.append(f"\tManual <{TKET_MANUAL_LINK}>\n") - content.append(f"\tExample notebooks <{TKET_EXAMPLES_LINK}>\n") - content.append(f"\tTKET website <{TKET_WEBSITE_LINK}>\n") - content.append( - "\n.. toctree::\n\t:caption: Links:\n\t:maxdepth: 1\n\n" - ) - content.append(f"\tbug tracker <{PYTKET_PROJECTQ_GITHUB}/issues>\n") - content.append(f"\tGitHub <{PYTKET_PROJECTQ_GITHUB}>\n") - content.append(f"\tPyPi <{PYTKET_PROJECTQ_PYPI_LINK}>\n") - - with open(index_rst, "w") as f: - f.writelines(content) - subprocess.run( - [ - "sphinx-build", - "-b", - "html", - "-D", - f"project=pytket-{MODULE}", - "-D", - f"version={'.'.join(v[:2])}", - "-D", - f"release={'.'.join(v)}", - ".", - "build", - ], - cwd=mod_docs, - ) - for htmlfile in mod_build.rglob("*.html"): - fix_links(htmlfile) - fix_links(mod_build / "searchindex.js") - conf_copy.unlink() - logo_copy_black.unlink() - logo_copy_white.unlink() - index_rst.unlink() - - -if __name__ == "__main__": - parser = argparse.ArgumentParser( - description="Build HTML documentation for pytket-projectq." - ) - parser.add_argument("-d", "--dest", help="copy artifacts into destination folder") - args = parser.parse_args() - - print("Building docs for modules:", MODULE) - build_module_docs() - - if args.dest is not None: - dest = Path(args.dest) - shutil.copytree( - MODULES_DIR / "docs" / "build", - dest, - dirs_exist_ok=True, - ) diff --git a/.github/workflows/docs/check-build-docs b/.github/workflows/docs/check-build-docs deleted file mode 100755 index 6812eb7..0000000 --- a/.github/workflows/docs/check-build-docs +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -./.github/workflows/docs/build-docs 1>out.txt 2>err.txt -cat out.txt err.txt -ERRS=`cat err.txt` -if [ ! -z $ERRS ] -then - echo "Docs build failed." - exit 1 -fi diff --git a/.github/workflows/docs/conf.py b/.github/workflows/docs/conf.py deleted file mode 100644 index f027627..0000000 --- a/.github/workflows/docs/conf.py +++ /dev/null @@ -1,145 +0,0 @@ -# -*- coding: utf-8 -*- - -# Configuration file for the Sphinx documentation builder. -# See https://www.sphinx-doc.org/en/master/usage/configuration.html - -author = "Quantinuum" - -extensions = [ - "sphinx.ext.autodoc", - "sphinx.ext.autosummary", - "sphinx.ext.intersphinx", - "sphinx.ext.mathjax", - "sphinx_copybutton", -] - -pygments_style = "borland" - -html_theme = "sphinx_book_theme" - -html_theme_options = { - "repository_url": "https://github.com/CQCL/pytket-projectq", - "use_repository_button": True, - "use_issues_button": True, - "logo": { - "image_light": "Quantinuum_logo_black.png", - "image_dark": "Quantinuum_logo_white.png", - }, -} - -html_static_path = ["_static"] - -html_css_files = ["custom.css"] - -# -- Extension configuration ------------------------------------------------- - -pytketdoc_base = "https://tket.quantinuum.com/api-docs/" - -intersphinx_mapping = { - "https://docs.python.org/3/": None, - pytketdoc_base: None, - "https://qiskit.org/documentation/": None, - "http://docs.qulacs.org/en/latest/": None, -} - -autodoc_member_order = "groupwise" - -# The following code is for resolving broken hyperlinks in the doc. - -import re -from typing import Any, Dict, List, Optional -from urllib.parse import urljoin - -from docutils import nodes -from docutils.nodes import Element, TextElement -from sphinx.application import Sphinx -from sphinx.environment import BuildEnvironment - -# Mappings for broken hyperlinks that intersphinx cannot resolve -external_url_mapping = { - "BasePass": urljoin(pytketdoc_base, "passes.html#pytket.passes.BasePass"), - "Predicate": urljoin(pytketdoc_base, "predicates.html#pytket.predicates.Predicate"), - "ResultHandle": urljoin( - pytketdoc_base, - "backends.html#pytket.backends.resulthandle.ResultHandle", - ), - "BackendResult": urljoin( - pytketdoc_base, - "backends.html#pytket.backends.backendresult.BackendResult", - ), - "Circuit": urljoin(pytketdoc_base, "circuit_class.html#pytket.circuit.Circuit"), - "BasisOrder": urljoin(pytketdoc_base, "circuit.html#pytket.circuit.BasisOrder"), - "QubitPauliOperator": urljoin( - pytketdoc_base, "utils.html#pytket.utils.QubitPauliOperator" - ), - "QubitPauliString": urljoin( - pytketdoc_base, "pauli.html#pytket.pauli.QubitPauliString" - ), -} - -# Correct mappings for intersphinx to resolve -custom_internal_mapping = { - "pytket.utils.outcomearray.OutcomeArray": "pytket.utils.OutcomeArray", - "pytket.utils.operators.QubitPauliOperator": "pytket.utils.QubitPauliOperator", - "pytket.backends.backend.Backend": "pytket.backends.Backend", - "qiskit.dagcircuit.dagcircuit.DAGCircuit": "qiskit.dagcircuit.DAGCircuit", - "qiskit.providers.basebackend.BaseBackend": "qiskit.providers.BaseBackend", - "qiskit.qobj.qasm_qobj.QasmQobj": "qiskit.qobj.QasmQobj", - "qiskit.result.result.Result": "qiskit.result.Result", -} - - -def add_reference( - app: Sphinx, env: BuildEnvironment, node: Element, contnode: TextElement -) -> Optional[nodes.reference]: - # Fix references in docstrings that are inherited from the base pytket.backends.Backend class. - mapping = app.config.external_url_mapping - if node.astext() in mapping: - newnode = nodes.reference( - "", - "", - internal=False, - refuri=mapping[node.astext()], - reftitle=node.get("reftitle", node.astext()), - ) - newnode.append(contnode) - return newnode - return None - - -def correct_signature( - app: Sphinx, - what: str, - name: str, - obj: Any, - options: Dict, - signature: str, - return_annotation: str, -) -> (str, str): - - new_signature = signature - new_return_annotation = return_annotation - for k, v in app.config.custom_internal_mapping.items(): - if signature is not None: - new_signature = new_signature.replace(k, v) - if return_annotation is not None: - new_return_annotation = new_return_annotation.replace(k, v) - # e.g. Replace by CXConfigType.Snake to avoid silent failure in later stages. - if new_signature is not None: - enums_signature = re.findall(r"<.+?\: \d+>", new_signature) - for e in enums_signature: - new_signature = new_signature.replace(e, e[1 : e.find(":")]) - - if new_return_annotation is not None: - enums_return = re.findall(r"<.+?\: \d+>", new_return_annotation) - for e in enums_return: - new_return_annotation = new_return_annotation.replace(e, e[1 : e.find(":")]) - - return new_signature, new_return_annotation - - -def setup(app): - app.add_config_value("custom_internal_mapping", {}, "env") - app.add_config_value("external_url_mapping", {}, "env") - app.connect("missing-reference", add_reference) - app.connect("autodoc-process-signature", correct_signature) diff --git a/.github/workflows/docs/intro.txt b/.github/workflows/docs/intro.txt deleted file mode 100644 index ce587b0..0000000 --- a/.github/workflows/docs/intro.txt +++ /dev/null @@ -1,10 +0,0 @@ -pytket-extensions -================= - -These extensions enable ``pytket` to be used in conjunction with other -platforms. Each extension adds either new methods to the ``pytket`` package to -convert between circuit representations, or new backends to which ``pytket`` -circuits can be submitted. - -.. _pytket: https://tket.quantinuum.com/api-docs/ -.. _Quantinuum: https://www.quantinuum.com/ diff --git a/.github/workflows/docs/requirements.txt b/.github/workflows/docs/requirements.txt deleted file mode 100644 index e893f3c..0000000 --- a/.github/workflows/docs/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -sphinx ~= 6.2 -sphinx_book_theme >= 1.0.1, <2.0 -sphinx-copybutton diff --git a/.github/workflows/docs/templates/searchbox.html b/.github/workflows/docs/templates/searchbox.html deleted file mode 100644 index e69de29..0000000 diff --git a/.gitignore b/.gitignore index 2b80d27..8bc0952 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,6 @@ obj docs/extensions .ipynb_checkpoints pytket/extensions/projectq/_metadata.py +.DS_Store +docs/pyproject.toml +docs/poetry.lock diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..fdc8b03 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "docs/pytket-docs-theming"] + path = docs/pytket-docs-theming + url = https://github.com/CQCL/pytket-docs-theming.git + branch = main diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..6e20b65 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,5 @@ +# Building the docs + +The docs are built by using the [pytket-docs-theming](https://github.com/CQCL/pytket-docs-theming/) repository as a git submodule. If there are issues with the docs build, feel free to open an issue or pull request there. + +For instructions on how to build the docs, take a look at the [extensions README](https://github.com/CQCL/pytket-docs-theming/blob/main/extensions/README.md). diff --git a/docs/_static/custom.css b/docs/_static/custom.css deleted file mode 100644 index 9c8a6ed..0000000 --- a/docs/_static/custom.css +++ /dev/null @@ -1,35 +0,0 @@ -.wy-side-nav-search, -.wy-nav-top { - background: #5A46BE; -} - -.wy-grid-for-nav, -.wy-body-for-nav, -.wy-nav-side, -.wy-side-scroll, -.wy-menu, -.wy-menu-vertical { - background-color: #FFFFFF; -} - -.wy-menu-vertical a:hover { - background-color: #d9d9d9; -} - -.btn-link:visited, -.btn-link, -a:visited, -.a.reference.external, -.a.reference.internal, -.wy-menu-vertical a, -.wy-menu-vertical li, -.wy-menu-vertical ul, -.span.pre, -.sig-param, -html[data-theme=light] { - --pst-color-inline-code: rgb(199, 37, 78) !important; -} - -.sig-name { - font-size: 1.25rem; -} \ No newline at end of file diff --git a/docs/build-docs.sh b/docs/build-docs.sh new file mode 100644 index 0000000..211c70a --- /dev/null +++ b/docs/build-docs.sh @@ -0,0 +1,21 @@ +#!/bin/bash +rm -rf build/ + +# Move theming elements into the docs folder +cp -R pytket-docs-theming/_static . +cp -R pytket-docs-theming/quantinuum-sphinx . +cp pytket-docs-theming/conf.py . + +# Get the name of the project +EXTENSION_NAME="$(basename "$(dirname `pwd`)")" + +# Correct github link in navbar +sed -i '' 's#CQCL/tket#CQCL/'$EXTENSION_NAME'#' _static/nav-config.js + +# Build the docs. Ensure we have the correct project title. +sphinx-build -b html -D html_title="$EXTENSION_NAME" . build + +# Remove copied files. This ensures reusability. +rm -r _static +rm -r quantinuum-sphinx +rm conf.py \ No newline at end of file diff --git a/docs/intro.txt b/docs/index.rst similarity index 77% rename from docs/intro.txt rename to docs/index.rst index ec97e03..f0c6809 100644 --- a/docs/intro.txt +++ b/docs/index.rst @@ -18,3 +18,9 @@ and Windows. To install, run: .. toctree:: api.rst changelog.rst + +.. toctree:: + :caption: Useful links + + Issue tracker + PyPi \ No newline at end of file diff --git a/docs/install.sh b/docs/install.sh new file mode 100644 index 0000000..3ca1079 --- /dev/null +++ b/docs/install.sh @@ -0,0 +1,9 @@ + +# Copy over poetry dependencies from theming repository +cp pytket-docs-theming/extensions/pyproject.toml . +cp pytket-docs-theming/extensions/poetry.lock . + +# Install the docs dependencies. Creates a .venv directory in docs +poetry install + +# NOTE: Editable wheel should be installed separately. \ No newline at end of file diff --git a/docs/pytket-docs-theming b/docs/pytket-docs-theming new file mode 160000 index 0000000..cfbe34c --- /dev/null +++ b/docs/pytket-docs-theming @@ -0,0 +1 @@ +Subproject commit cfbe34c48f88c56085b8ef65f640d0108b8a9fa6 diff --git a/pytket/extensions/projectq/backends/projectq_backend.py b/pytket/extensions/projectq/backends/projectq_backend.py index 2c049dd..f5b8308 100644 --- a/pytket/extensions/projectq/backends/projectq_backend.py +++ b/pytket/extensions/projectq/backends/projectq_backend.py @@ -286,7 +286,7 @@ def get_operator_expectation_value( """ ham = projectq.ops.QubitOperator() for term, coeff in operator._dict.items(): - if type(coeff) is complex and abs(coeff.imag) > 1e-12: # type: ignore + if type(coeff) is complex and abs(coeff.imag) > 1e-12: raise ValueError( "Operator is not Hermitian and cannot be converted to " "`projectq.ops.QubitOperator`."