From 70dfdf7f246a16598e23ce2608404a9a3bef55a1 Mon Sep 17 00:00:00 2001 From: Ali Asadi <10773383+maliasadi@users.noreply.github.com> Date: Mon, 9 Sep 2024 13:58:38 -0400 Subject: [PATCH] Replace toml with tomllib & tomli (#857) ### Before submitting Please complete the following checklist when submitting a PR: - [ ] All new features must include a unit test. If you've fixed a bug or added code that should be tested, add a test to the [`tests`](../tests) directory! - [ ] All new functions and code must be clearly commented and documented. If you do make documentation changes, make sure that the docs build and render correctly by running `make docs`. - [ ] Ensure that the test suite passes, by running `make test`. - [ ] Add a new entry to the `.github/CHANGELOG.md` file, summarizing the change, and including a link back to the PR. - [ ] Ensure that code is properly formatted by running `make format`. When all the above are checked, delete everything above the dashed line and fill in the pull request template. ------------------------------------------------------------------------------------------------------------ **Context:** Prefer `tomlkit` over `toml` for building Lightning wheels, and choose `tomli` and `tomllib` over `toml` when installing the package. **Description of the Change:** **Benefits:** - `tomli` and `tomllib` (for python > 3.10) provides a read-only, lightweight and fast toml parser compare to `toml` - `tomlkit` gets regular updates and provides support for all the toml updates and new standards. `toml` [hasn't been updated since Oct 2020](https://pypi.org/project/toml/). **Possible Drawbacks:** **Related GitHub Issues:** [sc-71707] --------- Co-authored-by: ringo-but-quantum Co-authored-by: Amintor Dusko <87949283+AmintorDusko@users.noreply.github.com> --- .github/CHANGELOG.md | 3 ++ .github/workflows/wheel_linux_aarch64.yml | 2 +- .../workflows/wheel_linux_aarch64_cuda.yml | 2 +- .github/workflows/wheel_linux_ppc64le.yml | 2 +- .github/workflows/wheel_linux_x86_64.yml | 2 +- .github/workflows/wheel_linux_x86_64_cuda.yml | 2 +- .github/workflows/wheel_macos_arm64.yml | 2 +- .github/workflows/wheel_macos_x86_64.yml | 2 +- .github/workflows/wheel_noarch.yml | 2 +- pennylane_lightning/core/_version.py | 2 +- pyproject.toml | 4 +-- scripts/configure_pyproject_toml.py | 32 +++++++++++++++++-- setup.py | 30 +++++++++++++++-- 13 files changed, 71 insertions(+), 16 deletions(-) diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index e4f135601a..fd7f2ec2b3 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -15,6 +15,9 @@ ### Improvements +* Prefer `tomlkit` over `toml` for building Lightning wheels, and choose `tomli` and `tomllib` over `toml` when installing the package. + [(#857)](https://github.com/PennyLaneAI/pennylane-lightning/pull/857) + * Update GitHub actions in response to a high-severity vulnerability. [(#887)](https://github.com/PennyLaneAI/pennylane-lightning/pull/887) diff --git a/.github/workflows/wheel_linux_aarch64.yml b/.github/workflows/wheel_linux_aarch64.yml index 3599194a42..938ea82f10 100644 --- a/.github/workflows/wheel_linux_aarch64.yml +++ b/.github/workflows/wheel_linux_aarch64.yml @@ -125,7 +125,7 @@ jobs: cp -rf ${{ github.workspace }}/Kokkos_install/${{ matrix.exec_model }}/* Kokkos/ - name: Install dependencies - run: python -m pip install cibuildwheel~=2.16.0 toml + run: python -m pip install cibuildwheel~=2.16.0 tomlkit - name: Configure pyproject.toml file run: PL_BACKEND="${{ matrix.pl_backend }}" python scripts/configure_pyproject_toml.py diff --git a/.github/workflows/wheel_linux_aarch64_cuda.yml b/.github/workflows/wheel_linux_aarch64_cuda.yml index 3a8a7cb960..cd4af3214c 100644 --- a/.github/workflows/wheel_linux_aarch64_cuda.yml +++ b/.github/workflows/wheel_linux_aarch64_cuda.yml @@ -49,7 +49,7 @@ jobs: uses: actions/checkout@v4 - name: Install cibuildwheel - run: python -m pip install cibuildwheel~=2.16.0 toml + run: python -m pip install cibuildwheel~=2.16.0 tomlkit - name: Configure pyproject.toml file run: PL_BACKEND="${{ matrix.pl_backend }}" python scripts/configure_pyproject_toml.py diff --git a/.github/workflows/wheel_linux_ppc64le.yml b/.github/workflows/wheel_linux_ppc64le.yml index ba831e52b1..88dd125997 100644 --- a/.github/workflows/wheel_linux_ppc64le.yml +++ b/.github/workflows/wheel_linux_ppc64le.yml @@ -124,7 +124,7 @@ jobs: cp -rf ${{ github.workspace }}/Kokkos_install/${{ matrix.exec_model }}/* Kokkos/ - name: Install dependencies - run: python -m pip install cibuildwheel~=2.16.0 toml + run: python -m pip install cibuildwheel~=2.16.0 tomlkit - uses: docker/setup-qemu-action@v3 name: Set up QEMU diff --git a/.github/workflows/wheel_linux_x86_64.yml b/.github/workflows/wheel_linux_x86_64.yml index 266b8b4381..0da9912b9b 100644 --- a/.github/workflows/wheel_linux_x86_64.yml +++ b/.github/workflows/wheel_linux_x86_64.yml @@ -141,7 +141,7 @@ jobs: dnf update -y && dnf install -y podman - name: Install dependencies - run: python3.10 -m pip install cibuildwheel~=2.16.0 toml + run: python3.10 -m pip install cibuildwheel~=2.16.0 tomlkit - name: Configure pyproject.toml file run: PL_BACKEND="${{ matrix.pl_backend }}" python3.10 scripts/configure_pyproject_toml.py diff --git a/.github/workflows/wheel_linux_x86_64_cuda.yml b/.github/workflows/wheel_linux_x86_64_cuda.yml index 05d2c53a7b..62d1a5ef8d 100644 --- a/.github/workflows/wheel_linux_x86_64_cuda.yml +++ b/.github/workflows/wheel_linux_x86_64_cuda.yml @@ -68,7 +68,7 @@ jobs: dnf update -y && dnf install -y podman - name: Install dependencies - run: python3.10 -m pip install cibuildwheel~=2.16.0 toml + run: python3.10 -m pip install cibuildwheel~=2.16.0 tomlkit - name: Configure pyproject.toml file run: PL_BACKEND="${{ matrix.pl_backend }}" python3.10 scripts/configure_pyproject_toml.py diff --git a/.github/workflows/wheel_macos_arm64.yml b/.github/workflows/wheel_macos_arm64.yml index dee3c56866..fd56822791 100644 --- a/.github/workflows/wheel_macos_arm64.yml +++ b/.github/workflows/wheel_macos_arm64.yml @@ -81,7 +81,7 @@ jobs: python-version: '3.10' - name: Install dependencies - run: python -m pip install cibuildwheel~=2.16.0 toml + run: python -m pip install cibuildwheel~=2.16.0 tomlkit - name: Configure pyproject.toml file run: PL_BACKEND="${{ matrix.pl_backend }}" python scripts/configure_pyproject_toml.py diff --git a/.github/workflows/wheel_macos_x86_64.yml b/.github/workflows/wheel_macos_x86_64.yml index 8f6c05d023..27dbfefe9d 100644 --- a/.github/workflows/wheel_macos_x86_64.yml +++ b/.github/workflows/wheel_macos_x86_64.yml @@ -130,7 +130,7 @@ jobs: python-version: '3.10' - name: Install dependencies - run: python -m pip install cibuildwheel~=2.16.0 toml + run: python -m pip install cibuildwheel~=2.16.0 tomlkit - name: Configure pyproject.toml file run: PL_BACKEND="${{ matrix.pl_backend }}" python scripts/configure_pyproject_toml.py diff --git a/.github/workflows/wheel_noarch.yml b/.github/workflows/wheel_noarch.yml index bac318b106..37b2b1982c 100644 --- a/.github/workflows/wheel_noarch.yml +++ b/.github/workflows/wheel_noarch.yml @@ -65,7 +65,7 @@ jobs: - name: Install dependencies if: ${{ matrix.pl_backend == 'lightning_qubit'}} run: | - python -m pip install toml + python -m pip install tomlkit - name: Configure pyproject.toml file if: ${{ matrix.pl_backend == 'lightning_qubit'}} diff --git a/pennylane_lightning/core/_version.py b/pennylane_lightning/core/_version.py index 2918ecaa86..90812ebe0a 100644 --- a/pennylane_lightning/core/_version.py +++ b/pennylane_lightning/core/_version.py @@ -16,4 +16,4 @@ Version number (major.minor.patch[-label]) """ -__version__ = "0.39.0-dev7" +__version__ = "0.39.0-dev8" diff --git a/pyproject.toml b/pyproject.toml index 722a59cfbb..2a0fbf63f0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = [ "cmake~=3.24.0", "ninja; platform_system!='Windows'", "setuptools>=42", "toml",] +requires = ["cmake~=3.24.0", "ninja; platform_system!='Windows'", "setuptools>=42", "tomli"] build-backend = "setuptools.build_meta" [project] @@ -8,7 +8,7 @@ description = "PennyLane-Lightning plugin" readme = "README.rst" requires-python = ">=3.10" classifiers = [ "Development Status :: 4 - Beta", "Environment :: Console", "Intended Audience :: Science/Research", "License :: OSI Approved :: Apache Software License", "Natural Language :: English", "Operating System :: MacOS :: MacOS X", "Operating System :: Microsoft :: Windows", "Operating System :: POSIX", "Operating System :: POSIX :: Linux", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Topic :: Scientific/Engineering :: Physics",] -dependencies = [ "pennylane>=0.37",] +dependencies = ["pennylane>=0.37"] dynamic = [ "version",] [[project.maintainers]] name = "Xanadu Quantum Technologies Inc." diff --git a/scripts/configure_pyproject_toml.py b/scripts/configure_pyproject_toml.py index 2c5be36323..56510fc6cb 100755 --- a/scripts/configure_pyproject_toml.py +++ b/scripts/configure_pyproject_toml.py @@ -16,9 +16,10 @@ """ import argparse import os +from importlib import import_module +from importlib.util import find_spec from pathlib import Path -import toml from backend_support import backend, device_name path_to_project = Path(__file__).parent.parent.absolute() @@ -28,6 +29,19 @@ version = f.readlines()[-1].split()[-1].strip("\"'") +# ------------------------ +# Find the toml parser. +# ------------------------ +has_toml = False +toml_libs = ["tomlkit", "toml"] # "tomllib" and "tomli" do not implement 'dump'. +for pkg in toml_libs: + spec = find_spec(pkg) + if spec: + toml = import_module(pkg) + has_toml = True + break + + ######################################################################## # Parsing arguments ######################################################################## @@ -57,7 +71,19 @@ def parse_args(): pyproject_path = os.path.join(parsed_args.path, "pyproject.toml") - pyproject = toml.load(pyproject_path) + if not has_toml: + raise ImportError( + "A TOML parser is required to configure 'pyproject.toml'. " + f"We support any of the following TOML parsers: {toml_libs} " + "You can install tomlkit via `pip install tomlkit`." + ) + + try: + with open(pyproject_path, "rb") as f: + pyproject = toml.load(f) + except TypeError: + # To support toml and tomli APIs + pyproject = toml.load(pyproject_path) # ------------------------ # Configure Build. @@ -66,7 +92,7 @@ def parse_args(): "cmake~=3.24.0", "ninja; platform_system!='Windows'", "setuptools>=42", - "toml", + "tomli", ] if backend == "lightning_gpu": requires.append("custatevec-cu12") diff --git a/setup.py b/setup.py index cd51c3a93d..039cc5e6e0 100644 --- a/setup.py +++ b/setup.py @@ -16,13 +16,39 @@ import subprocess import shutil import sys -import toml + +from importlib import import_module +from importlib.util import find_spec from pathlib import Path from setuptools import setup, Extension, find_namespace_packages from setuptools.command.build_ext import build_ext -project_name = toml.load("pyproject.toml")['project']['name'] + +has_toml = False +toml_libs = ["tomli", "tomllib", "tomlkit", "toml"] +for pkg in toml_libs: + spec = find_spec(pkg) + if spec: + toml = import_module(pkg) + has_toml = True + break + +if not has_toml: + raise ImportError( + "A TOML parser is required to configure 'pyproject.toml'. " + f"We support any of the following TOML parsers: {toml_libs} " + "You can install tomlkit via `pip install tomlkit`, or tomli via `pip install tomli`, " + "or use Python 3.11 or above which natively offers the tomllib library." + ) + +try: + with open("pyproject.toml", "rb") as f: + project_name = toml.load(f)['project']['name'] +except TypeError: + # To support toml and tomli APIs + project_name = toml.load("pyproject.toml")['project']['name'] + backend = project_name.replace("PennyLane_", "").lower() if (backend == "lightning"): backend = "lightning_qubit"