diff --git a/.gemini/styleguide.md b/.gemini/styleguide.md index dfb5ce8af..32ce88d8f 100644 --- a/.gemini/styleguide.md +++ b/.gemini/styleguide.md @@ -1,23 +1,29 @@ # qsim style guide -This style guide outlines the coding conventions for this project. There are -separate subsections for Python, C++, and other file types below. +This style guide for Gemini outlines the coding conventions for this project. ## General guidance ### Overall principles -* _Readability_: Code should be easy to understand for all team members. +* _Readability_: Code must be easy for humans to understand. Prefer clarity + over cleverness. Write elegant, well-structured code. -* _Maintainability_: Code should be easy to modify and extend. +* _Maintainability_: Code must be easy to modify and extend. -* _Consistency_: Adhering to a consistent style across all projects improves - collaboration and reduces errors. +* _Consistency_: Be consistent with naming convention, style, and other + patterns in the code base. * _Performance_: While readability is paramount, code should be efficient. ### Overall development approach +* Code should be modular and adhere to language idioms and best practices. + +* Data obtained from the user or read from a file should be validated. + Identify and guard against potential vulnerabilities in data handling or + input validation. + * When new functions, classes, and files are introduced, they should also have corresponding tests. Existing tests must continue to pass (or be updated) when changes are introduced, and code should be covered by tests. @@ -28,16 +34,16 @@ separate subsections for Python, C++, and other file types below. * Tests must be independent and must not rely on the state of other tests. Setup and teardown functions should be used to create a clean environment - for each test run. External dependencies (e.g., databases, network - services, file system) must be mocked to ensure the test is isolated to the - unit under test. + for each test run. External dependencies (e.g., databases, network services, + file system) must be mocked to ensure the test is isolated to the unit under + test. * Make sure to cover edge cases: write tests for invalid inputs, null values, empty arrays, zero values, and off-by-one errors. -* Use asserts intelligently. Test assertions should be specific: instead of - just asserting `true`, assert that a specific value equals an expected - value. Provide meaningful failure messages. +* Use asserts in tests intelligently. Test assertions should be specific: + instead of just asserting `true`, assert that a specific value equals an + expected value. Provide meaningful failure messages. ### Overall code format conventions @@ -77,7 +83,7 @@ present at the top level of this project repository): * [`.yamllint.yaml`](../.yamllint.yaml) for YAML files. -### Overall code commenting conventions +### Overall code comment conventions Every source file must begin with a header comment with the copyright and license. We use the Apache 2.0 license. Here is an example of the required file @@ -99,23 +105,20 @@ header for a Python language code file: # limitations under the License. ``` -License headers are necessary on Python, C++, Bash/shell, and other programming +License headers are necessary in Python, C++, Bash/shell, and other programming language files, as well as configuration files in YAML, TOML, ini, and other config file formats. They are not necessary in Markdown or plain text files. For comments in other parts of the files, follow these guidelines: * _Write clear and concise comments_: Comments should explain the "why", not - the "what". The code itself shows what it's doing. The comments should - explain the intent, trade-offs, and reasoning behind the implementation. + the "what". The comments should explain the intent, trade-offs, and + reasoning behind the implementation. * _Comment sparingly_: Well-written code should be self-documenting where possible. It's not necessary to add comments for code fragments that can reasonably be assumed to be self-explanatory. -* _Use complete sentences_: Start comments with a capital letter, use - proper punctuation, and use proper grammar. - ## Python-specific guidance This section outlines coding conventions for Python code in this project. @@ -161,9 +164,9 @@ naming, we can reduce cognitive load on human users and developers. amplitudes. If a function expects a NumPy array of amplitudes, its type annotation should be `np.ndarray`. -### Docstrings and documentation +### Python docstrings and documentation -For Python code, this project uses [Google style doc strings]( +This project uses [Google style doc strings]( http://google.github.io/styleguide/pyguide.html#381-docstrings) with a Markdown flavor and support for LaTeX. Docstrings use tripe double quotes, and the first line should be a concise one-line summary of the function or object. @@ -227,7 +230,7 @@ The following programs can be used to perform some automated formatting. ### Python type annotations -This project makes extensive use of type annotations as defined by [PEP 484]( +This project uses type annotations as defined by [PEP 484]( https://peps.python.org/pep-0484/). All new code should use type annotations where possible, especially on public classes and functions to serve as documentation, but also on internal code so that the `mypy` type checker can @@ -298,3 +301,14 @@ To build tests without running them, instead use: ```shell bzel build tests:all ``` + +## Shell script-specific guidance + +Shell scripts should use Bash. + +### Shell script formatting + +Use the [Google Shell Style Guide]( +https://google.github.io/styleguide/shellguide.html) with the following changes: + +* Use indentation of 4 spaces, not 2. diff --git a/.github/actionlint.yaml b/.github/actionlint.yaml index a4e7594b9..bb1b70b7e 100644 --- a/.github/actionlint.yaml +++ b/.github/actionlint.yaml @@ -12,13 +12,35 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Summary: config actionlint (https://github.com/rhysd/actionlint) for certain -# things we use. +# Summary: configure actionlint (https://github.com/rhysd/actionlint) to +# recognize action runner names/labels that we use. self-hosted-runner: - # We don't have self-hosted runners, but we do use some of the "partner" - # runner images from https://github.com/actions/partner-runner-images - # and some runners that actionlint doesn't currently recognize. labels: + # Defined in Quantumlib org. + - ubuntu-22.04-arm64-2-core + - ubuntu-22.04-arm64-8-core + - ubuntu-22.04-arm64-16-core + + - ubuntu-22.04-x64-2-core + - ubuntu-22.04-x64-8-core + - ubuntu-22.04-x64-16-core + + - ubuntu-24.04-arm64-2-core + - ubuntu-24.04-arm64-8-core + - ubuntu-24.04-arm64-16-core + + - ubuntu-24.04-x64-2-core + - ubuntu-24.04-x64-8-core + - ubuntu-24.04-x64-16-core + + - windows-2022-x64-8-core + - windows-2025-x64-8-core + - windows-2025-x64-16-core + + # From https://github.com/actions/partner-runner-images - ubuntu-24.04-arm + + # New from GitHub (late 2025) but currently not known by actionlint. + # https://docs.github.com/en/actions/reference/runners/github-hosted-runners - ubuntu-slim diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 4a9106311..97c78dd5c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -67,16 +67,18 @@ jobs: fetch-depth: 0 - name: Set up Python - uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v5 + uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v5 with: python-version: ${{env.python-version}} cache: pip - cache-dependency-path: | - requirements.txt - dev-requirements.txt + + - name: Upgrade pip + run: python -m pip install --upgrade pip - name: Install dependencies - run: pip install -r requirements.txt -r dev-requirements.txt + run: | + pip install -r requirements.txt + pip install --group dev - name: Check format continue-on-error: ${{inputs.soft-linting == 'true'}} @@ -230,17 +232,19 @@ jobs: submodules: recursive - name: Set up Python - uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v5 + uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v5 id: setup with: python-version: ${{matrix.python_version}} cache: pip - cache-dependency-path: | - requirements.txt - dev-requirements.txt + + - name: Upgrade pip + run: python -m pip install --upgrade pip - name: Install dependencies - run: pip install -r requirements.txt -r dev-requirements.txt + run: | + pip install -r requirements.txt + pip install --group dev - name: Set up Bazel uses: './.github/actions/set-up-bazel' @@ -316,16 +320,18 @@ jobs: submodules: recursive - name: Set up Python - uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v5 + uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v5 with: python-version: ${{env.python-version}} cache: pip - cache-dependency-path: | - requirements.txt - dev-requirements.txt + + - name: Upgrade pip + run: python -m pip install --upgrade pip - name: Install dependencies - run: pip install -r requirements.txt -r dev-requirements.txt + run: | + pip install -r requirements.txt + pip install --group dev - name: Set up Bazel uses: './.github/actions/set-up-bazel' @@ -371,16 +377,18 @@ jobs: submodules: recursive - name: Set up Python - uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v5 + uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v5 with: python-version: ${{env.python-version}} cache: pip - cache-dependency-path: | - requirements.txt - dev-requirements.txt + + - name: Upgrade pip + run: python -m pip install --upgrade pip - name: Install dependencies - run: pip install -r requirements.txt -r dev-requirements.txt + run: | + pip install -r requirements.txt + pip install --group dev - name: Set up Bazel uses: './.github/actions/set-up-bazel' diff --git a/.github/workflows/cirq_compatibility.yml b/.github/workflows/cirq_compatibility.yml index 271e953a4..c896027fc 100644 --- a/.github/workflows/cirq_compatibility.yml +++ b/.github/workflows/cirq_compatibility.yml @@ -46,21 +46,21 @@ jobs: submodules: recursive - name: Set up Python with caching of pip dependencies - uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v5 + uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v5 with: python-version: '3.12' cache: pip - cache-dependency-path: | - requirements.txt - dev-requirements.txt + + - name: Upgrade pip + run: python -m pip install --upgrade pip - name: Install latest dev version of Cirq run: pip install --upgrade cirq~=1.0.dev - - name: Install qsim dev requirements + - name: Install dependencies run: | pip install -r requirements.txt - pip install -r dev-requirements.txt + pip install --group dev - name: Run Python tests env: diff --git a/.github/workflows/osv-scanner.yaml b/.github/workflows/osv-scanner.yaml deleted file mode 100644 index b5e83a46c..000000000 --- a/.github/workflows/osv-scanner.yaml +++ /dev/null @@ -1,145 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -name: OSV scan -run-name: Run open-source vulnerabilities (OSV) scanner - -# The OSV scanner is a dependency vulnerability scanner that identifies known -# vulnerabilities in a project's dependencies. It supports C/C++, Python, Java, -# JavaScript, and others. The findings are reported in the repo's code-scanning -# results page, https://github.com/quantumlib/REPO/security/code-scanning/. -# For more OSV scanner examples and options, including how to ignore specific -# vulnerabilities, see https://google.github.io/osv-scanner/github-action/. - -on: - schedule: - # Run weekly on Saturdays. - - cron: '30 10 * * 6' - - pull_request: - types: [opened, synchronize] - branches: - - main - - # Allow manual invocation. - workflow_dispatch: - inputs: - debug: - description: 'Run with debugging options' - type: boolean - default: true - -concurrency: - # Cancel any previously-started but still active runs on the same branch. - cancel-in-progress: true - group: ${{github.workflow}}-${{github.event.pull_request.number||github.ref}} - -# Declare default workflow permissions as read only. -permissions: read-all - -jobs: - osv-scan: - if: github.repository_owner == 'quantumlib' - name: OSV scanner - runs-on: ubuntu-24.04 - timeout-minutes: 30 - permissions: - # Needed to upload the results to code-scanning dashboard: - security-events: write - env: - # Setting Bash SHELLOPTS here takes effect for all shell commands below. - SHELLOPTS: ${{inputs.debug && 'xtrace' || '' }} - steps: - - name: Check out a copy of the git repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - with: - fetch-depth: 0 - - - name: Check out the target branch - run: | - git checkout ${{github.base_ref || github.ref_name}} - git submodule update --recursive - - - name: Run OSV scanner on existing code - # yamllint disable rule:line-length - uses: google/osv-scanner-action/osv-scanner-action@b77c075a1235514558f0eb88dbd31e22c45e0cd2 # v2.3.0 - continue-on-error: true - with: - scan-args: |- - --include-git-root - --format=json - --output=old-results.json - --recursive - ./ - - - name: Check out current branch - # Use -f in case any changes were made by osv-scanner. - run: | - git checkout -f "$GITHUB_SHA" - git submodule update --recursive - - - name: Run OSV scanner on new code - # yamllint disable rule:line-length - uses: google/osv-scanner-action/osv-scanner-action@b77c075a1235514558f0eb88dbd31e22c45e0cd2 # v2.3.0 - continue-on-error: true - with: - scan-args: |- - --include-git-root - --format=json - --output=new-results.json - --recursive - ./ - - - name: Run the OSV scanner reporter for the job summary page - # yamllint disable rule:line-length - uses: google/osv-scanner-action/osv-reporter-action@b77c075a1235514558f0eb88dbd31e22c45e0cd2 # v2.3.0 - with: - scan-args: |- - --output=markdown:output.md - --old=old-results.json - --new=new-results.json - --fail-on-vuln=false - - - name: Write the results to the job summary page - run: cat output.md >> "$GITHUB_STEP_SUMMARY" - - - name: Run the OSV scanner reporter for the code-scanning dashboard - # yamllint disable rule:line-length - uses: google/osv-scanner-action/osv-reporter-action@b77c075a1235514558f0eb88dbd31e22c45e0cd2 # v2.3.0 - with: - scan-args: |- - --output=osv-results.sarif - --old=old-results.json - --new=new-results.json - --gh-annotations=true - --fail-on-vuln=true - - - name: Upload results to the repository's code-scanning results dashboard - id: upload_artifact - # yamllint disable rule:line-length - uses: github/codeql-action/upload-sarif@ba454b8ab46733eb6145342877cd148270bb77ab # codeql-bundle-v2.23.5 - with: - sarif_file: osv-results.sarif - - - if: github.event.inputs.debug == true - name: Upload results as artifacts to the workflow Summary page - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 - with: - name: SARIF file - path: osv-results.sarif - retention-days: 5 - - - name: Print an alert message if an error occurred - if: ${{always() && steps.upload_artifact.outcome == 'failure'}} - run: echo '::error::Artifact upload failed. Check the workflow logs.' diff --git a/Dockerfile b/Dockerfile index 7d82f2eb5..8856526fe 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,7 +20,7 @@ ARG CUDA_PATH ENV PATH="$CUDA_PATH/bin:$PATH" # Update package list & install some basic tools we'll need. -# hadolint ignore=DL3009,DL3008 +# hadolint ignore=DL3008,DL3009 RUN apt-get update && \ apt-get install -y make g++ wget git --no-install-recommends && \ apt-get install -y python3-dev python3-pip python3-venv --no-install-recommends @@ -38,7 +38,7 @@ COPY ./lib/ /qsim/lib/ COPY ./pybind_interface/ /qsim/lib/ COPY ./qsimcirq_tests/ /qsim/qsimcirq_tests/ COPY ./requirements.txt /qsim/requirements.txt -COPY ./dev-requirements.txt /qsim/dev-requirements.txt +COPY ./pyproject.toml /qsim/pyproject.toml # Create venv to avoid collision between system packages and what we install. RUN python3 -m venv --upgrade-deps test_env @@ -46,13 +46,15 @@ RUN python3 -m venv --upgrade-deps test_env # Activate venv. ENV PATH="/test_env/bin:$PATH" -# Install qsim requirements. -# hadolint ignore=DL3042 -RUN python3 -m pip install -r /qsim/requirements.txt && \ - python3 -m pip install -r /qsim/dev-requirements.txt +WORKDIR /qsim + +# Install qsim development requirements. +# hadolint ignore=DL3013 +RUN python3 -m pip install --no-cache-dir --upgrade pip && \ + python3 -m pip install --no-cache-dir -r requirements.txt && \ + python3 -m pip install --no-cache-dir --group dev # Compile qsim. -WORKDIR /qsim/ RUN make -j qsim ENTRYPOINT ["/qsim/apps/qsim_base.x"] diff --git a/MANIFEST.in b/MANIFEST.in index 4b487267f..7bf618414 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,6 +1,5 @@ -include requirements.txt -include dev-requirements.txt include CMakeLists.txt +include requirements.txt graft pybind_interface graft lib diff --git a/dev-requirements.txt b/dev-requirements.txt deleted file mode 100644 index 2a0fc0a36..000000000 --- a/dev-requirements.txt +++ /dev/null @@ -1,12 +0,0 @@ -cmake~=3.28.1 -black~=25.9.0 -flynt~=1.0 -isort[colors]~=6.0.1 -# The global option to pybind11 makes it include CMake files in a location where -# CMake will find them. It makes a crucial difference in some environments. -pybind11[global] -pylint~=4.0.2 -pytest -pytest-xdist -py-cpuinfo -setuptools>=78.1.1 diff --git a/docs/install_qsimcirq.md b/docs/install_qsimcirq.md index 6887a57f1..9636fb835 100644 --- a/docs/install_qsimcirq.md +++ b/docs/install_qsimcirq.md @@ -13,15 +13,16 @@ directly in C++ code without building and installing the qsimcirq interface. Prior to installation, consider opening a [virtual environment](https://packaging.python.org/guides/installing-using-pip-and-virtual-environments/). -Prerequisites are included in the -[`requirements.txt`](https://github.com/quantumlib/qsim/blob/main/requirements.txt) -file, and will be automatically installed along with qsimcirq. - -If you'd like to develop qsimcirq, a separate set of dependencies are includes -in the -[`dev-requirements.txt`](https://github.com/quantumlib/qsim/blob/main/dev-requirements.txt) -file. You can install them with `pip3 install -r dev-requirements.txt` or -`pip3 install qsimcirq[dev]`. +Prerequisites are defined in the +[`pyproject.toml`](https://github.com/quantumlib/qsim/blob/main/pyproject.toml) +file, and will be automatically installed along with qsimcirq when you install +it with pip. + +If you'd like to develop qsimcirq, a separate set of dependencies for +development are included in the +[`pyproject.toml`](https://github.com/quantumlib/qsim/blob/main/pyproject.toml) +file. You can install them with `pip3 install --group dev`. (You will need +pip version 25.1 or higher.) ## Linux installation diff --git a/pyproject.toml b/pyproject.toml index 37d714455..a3438abb6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,28 +12,117 @@ # See the License for the specific language governing permissions and # limitations under the License. +# Note: development dependencies are in group "dev" under [dependency-groups]. +# Install them using "pip install --group dev". + +[project] +name = "qsimcirq" +dynamic = ["version", "dependencies"] +description = "High-performance quantum circuit simulator for C++ and Python." +authors = [ + { name = "The qsim/qsimh Developers", email = "qsim-qsimh-dev@googlegroups.com" } +] +maintainers = [ + { name = "Google Quantum AI", email = "quantum-oss-maintainers@google.com" } +] +license = "Apache-2.0" +requires-python = ">=3.10.0" +readme = "README.md" +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Environment :: GPU :: NVIDIA CUDA", + "Intended Audience :: Developers", + "Intended Audience :: Science/Research", + "Operating System :: MacOS :: MacOS X", + "Operating System :: Microsoft :: Windows", + "Operating System :: POSIX :: Linux", + "Programming Language :: C++", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Topic :: Scientific/Engineering :: Quantum Computing", + "Topic :: Software Development :: Libraries :: Python Modules", + "Typing :: Typed", +] +keywords = [ + "algorithms", + "cirq", + "nisq", + "quantum algorithm development", + "quantum circuit simulator", + "quantum computer simulator", + "quantum computing", + "quantum programming", + "quantum simulation", + "quantum", + "schrödinger-feynman simulation", + "simulation", + "state vector simulator", +] + +[project.urls] +homepage = "https://quantumai.google/qsim" +documentation = "https://quantumai.google/qsim" +source = "https://github.com/quantumlib/qsim" +download = "https://pypi.org/project/qsimcirq/#files" +tracker = "https://github.com/quantumlib/qsim/issues" + +[dependency-groups] +# Development dependencies. Install these with "pip install --group dev". +dev = [ + "black~=25.9.0", + "cibuildwheel", + "flynt~=1.0", + "isort[colors]~=6.0.1", + "py-cpuinfo", + "pylint~=4.0.2", + "pytest", + "pytest-xdist", +] + [build-system] +build-backend = "setuptools.build_meta" requires = [ - "packaging", - "setuptools>=78.1.1", - "pybind11[global]", - # "pip install" from sources needs to build Pybind, which needs CMake too. - "cmake~=3.28.1", + "setuptools>=78.1.1", + "setuptools-scm[toml]>=6.2", + "wheel", ] -build-backend = "setuptools.build_meta" + +[tool.setuptools] +packages = ["qsimcirq"] +package-data = {"qsimcirq" = ["py.typed"]} + +[tool.setuptools.dynamic] +version = {attr = "qsimcirq._version.__version__"} +# Install/runtime dependencies. "pip install qsim" installs these automatically. +dependencies = {file = ["requirements.txt"] } [tool.cibuildwheel] -test-extras = "dev" +build = "cp310-* cp311-* cp312-* cp313-*" dependency-versions = "latest" enable = ["cpython-prerelease"] environment.PIP_PREFER_BINARY = "1" # Due to package & module name conflict, temporarily move it away to run tests: -before-test = "mv {package}/qsimcirq /tmp" -test-command = "pytest -s -v {package}/qsimcirq_tests/qsimcirq_test.py && mv /tmp/qsimcirq {package}" +before-test = "pip install --group dev && mv {package}/qsimcirq /tmp" +test-command = """ +pytest -n auto -s -v {package}/qsimcirq_tests/qsimcirq_test.py && +mv /tmp/qsimcirq {package} +""" [tool.cibuildwheel.macos] -before-build = "brew install -q libomp llvm@19 && brew unlink libomp && brew unlink llvm@19 && brew link --force libomp && brew link --force llvm@19" -repair-wheel-command = "delocate-listdeps {wheel} && delocate-wheel --verbose --require-archs {delocate_archs} -w {dest_dir} {wheel}" +before-build = """ +brew install -q libomp llvm@19 && +brew unlink libomp && +brew unlink llvm@19 && +brew link --force libomp && +brew link --force llvm@19 +""" +repair-wheel-command = """ +delocate-listdeps {wheel} && +delocate-wheel --verbose --require-archs {delocate_archs} -w {dest_dir} {wheel} +""" [tool.cibuildwheel.linux] manylinux-x86_64-image = "manylinux2014" @@ -43,3 +132,11 @@ skip = "*musllinux*" [tool.black] target-version = ['py310', 'py311', 'py312', 'py313'] extend-exclude = 'third_party' + +[tool.isort] +profile = 'black' +order_by_type = false # Sort alphabetically, irrespective of case. +skip_gitignore = true +combine_as_imports = true +known_first_party = ["cirq*"] +extend_skip = ["__init__.py"] diff --git a/requirements.txt b/requirements.txt index 21e8a4ade..b54fae5d5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,13 @@ +# Runtime dependencies for qsimcirq. This file is referenced by pyproject.toml. + absl-py cirq-core~=1.0 -numpy>=1.26.0 +cmake~=3.28.1 +numpy>=1.26.0,<2.0; python_version < '3.11' +numpy>=2.0; python_version >= '3.11' +pybind11[global]<3.0 + +# These are transitive dependencies we need to constrain to avoid unresolvable +# installation conflicts due to them requiring higher Python versions: +scipy<1.16; python_version < '3.11' +contourpy<1.3; python_version < '3.11' diff --git a/setup.py b/setup.py index 328b27cdd..d3ccfa54c 100644 --- a/setup.py +++ b/setup.py @@ -24,6 +24,10 @@ from setuptools import Extension, setup from setuptools.command.build_ext import build_ext +# qsimcirq/_version.py contains the source of truth for the version nhumber. +__version__ = runpy.run_path("qsimcirq/_version.py")["__version__"] +assert __version__, "The version string must not be empty" + class CMakeExtension(Extension): def __init__(self, name, sourcedir=""): @@ -67,6 +71,8 @@ def build_extension(self, ext): "-DCMAKE_CUDA_COMPILER=nvcc", ] + # Append additional CMake arguments from the environment variable. + # This is e.g. used by cibuildwheel to force a certain C++ standard. additional_cmake_args = os.environ.get("CMAKE_ARGS", "") if additional_cmake_args: cmake_args += additional_cmake_args.split() @@ -110,9 +116,7 @@ def build_extension(self, ext): env = os.environ.copy() cxxflags = env.get("CXXFLAGS", "") - env["CXXFLAGS"] = ( - f'{cxxflags} -DVERSION_INFO=\\"{self.distribution.get_version()}\\"' - ) + env["CXXFLAGS"] = f'{cxxflags} -DVERSION_INFO=\\"{__version__}\\"' if not os.path.exists(self.build_temp): os.makedirs(self.build_temp) subprocess.check_call( @@ -124,42 +128,7 @@ def build_extension(self, ext): ) -with open("requirements.txt") as f: - requirements = [ - line.strip() for line in f if line.strip() and not line.strip().startswith("#") - ] -with open("dev-requirements.txt") as f: - dev_requirements = [ - line.strip() for line in f if line.strip() and not line.strip().startswith("#") - ] - -description = "Schrödinger and Schrödinger-Feynman simulators for quantum circuits." - -# README file as long_description. -with open("README.md", encoding="utf-8") as f: - long_description = f.read() - -__version__ = runpy.run_path("qsimcirq/_version.py")["__version__"] -if not __version__: - raise ValueError("Version string cannot be empty") - setup( - name="qsimcirq", - version=__version__, - url="https://github.com/quantumlib/qsim", - author="The qsim/qsimh Developers", - author_email="qsim-qsimh-dev@googlegroups.com", - maintainer="Google Quantum AI", - maintainer_email="quantum-oss-maintainers@google.com", - python_requires=">=3.10.0", - install_requires=requirements, - extras_require={ - "dev": dev_requirements, - }, - license="Apache-2.0", - description=description, - long_description=long_description, - long_description_content_type="text/markdown", ext_modules=[ CMakeExtension("qsimcirq/qsim_avx512"), CMakeExtension("qsimcirq/qsim_avx2"), @@ -170,49 +139,5 @@ def build_extension(self, ext): CMakeExtension("qsimcirq/qsim_decide"), CMakeExtension("qsimcirq/qsim_hip"), ], - cmdclass=dict(build_ext=CMakeBuild), - zip_safe=False, - packages=["qsimcirq"], - package_data={"qsimcirq": ["py.typed"]}, - classifiers=[ - "Development Status :: 5 - Production/Stable", - "Environment :: GPU :: NVIDIA CUDA", - "Intended Audience :: Developers", - "Intended Audience :: Science/Research", - "Operating System :: MacOS :: MacOS X", - "Operating System :: Microsoft :: Windows", - "Operating System :: POSIX :: Linux", - "Programming Language :: C++", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3.13", - "Topic :: Scientific/Engineering :: Quantum Computing", - "Topic :: Software Development :: Libraries :: Python Modules", - "Typing :: Typed", - ], - keywords=[ - "algorithms", - "api", - "application programming interface", - "cirq", - "google quantum", - "google", - "nisq", - "python", - "quantum algorithm development", - "quantum circuit simulator", - "quantum computer simulator", - "quantum computing", - "quantum computing research", - "quantum programming", - "quantum simulation", - "quantum", - "schrödinger-feynman simulation", - "sdk", - "simulation", - "state vector simulator", - "software development kit", - ], + cmdclass={"build_ext": CMakeBuild}, )