Skip to content

Commit ee91a94

Browse files
committed
Refactor notebook testing framework with enhanced logging and configuration
- Introduced logging configuration to output messages to console with INFO level. - Added constants for default timeout and environment variable names in a new constants module. - Refactored notebook execution tests to use parameterization and improved error handling. - Created a helper function to print formatted section headers for better readability. - Updated the main execution block to provide a summary of notebook tests with detailed logging. - Added an __init__.py file to the tests directory for package recognition.
1 parent 88fcdc2 commit ee91a94

File tree

13 files changed

+608
-218
lines changed

13 files changed

+608
-218
lines changed

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM python:14-slim
1+
FROM python:3.13-slim
22

33
WORKDIR /workspace
44

README.md

Lines changed: 49 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,97 +1,89 @@
11
# IonQ Quantum Computing Samples
22

3-
This repository contains Python samples exploring quantum computing on IonQ's platform using various quantum programming libraries. These examples are a great place to start if you're interested in quantum computation, but aren't familiar with any of the libraries out there.
3+
Python samples demonstrating quantum computing on IonQ's platform using popular quantum libraries. A great starting point for exploring quantum computation.
44

5-
If you're looking for advanced and in-depth examples for a given library that implement a specific algorithm, check out some of the other projects in the [ionq-samples](https://github.com/ionq-samples) organization on GitHub.
5+
For advanced examples implementing specific algorithms, check out the [ionq-samples](https://github.com/ionq-samples) organization.
66

77
---
88

9-
## Prerequisites
9+
## Quick Start
1010

11-
There are a wide variety of ways to run these notebooks, but for starters you'll need:
11+
### Prerequisites
1212

13-
1. [Python](https://www.python.org/downloads/) installed, using a version between 3.10 and 3.13.
14-
2. A [virtual environment](https://docs.python.org/3/library/venv.html) to help ensure your dependencies don't conflict with anything else you have installed.
15-
3. An [IonQ API key](https://cloud.ionq.com/settings/keys), which optionally you can store as an environment variable for ease of use. Our notebooks expect to find it stored as `IONQ_API_KEY`.
16-
4. An installation of the library you're wanting to run. You can install all libraries using one of the following methods:
13+
- Python 3.10-3.13
14+
- [IonQ API key](https://cloud.ionq.com/settings/keys) (set as `IONQ_API_KEY` environment variable)
1715

18-
**Option 1: Using uv (Fastest - Recommended)**
16+
### Installation
1917

20-
[uv](https://github.com/astral-sh/uv) is an extremely fast Python package installer and resolver:
18+
**Using pip:**
19+
```bash
20+
pip install -e .
21+
```
2122

22-
```shell
23-
# Install uv (if not already installed)
24-
curl -LsSf https://astral.sh/uv/install.sh | sh
23+
**Using uv (faster):**
24+
```bash
25+
curl -LsSf https://astral.sh/uv/install.sh | sh
26+
uv pip install -e .
27+
```
2528

26-
# Install all dependencies
27-
uv pip install -e .
28-
```
29+
**Using conda:**
30+
```bash
31+
conda env create -f environment.yml
32+
```
2933

30-
**Option 2: Using Conda**
34+
### Running Notebooks
3135

32-
```shell
33-
conda env create -f environment.yml
34-
```
36+
**Jupyter:**
37+
```bash
38+
jupyter notebook
39+
```
3540

36-
**Option 3: Using pip**
41+
**VS Code:**
42+
Open any `.ipynb` file and select a Python kernel.
3743

38-
```shell
39-
pip install -e .
40-
```
44+
**Cloud:**
45+
Click the ![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg) badge in each notebook.
4146

4247
---
4348

4449
## Docker
4550

46-
For a reproducible environment with all dependencies pre-installed:
51+
Run in a containerized environment:
4752

48-
```shell
49-
# Build the image (linux/x86_64 required for cudaq)
53+
```bash
54+
# Build
5055
docker build --platform=linux/x86_64 -t ionq-notebooks .
5156

52-
# Run with your API key
53-
docker run -p 8888:8888 -e IONQ_API_KEY="your_api_key_here" ionq-notebooks
57+
# Run
58+
docker run -p 8888:8888 -e IONQ_API_KEY="your_api_key" ionq-notebooks
5459
```
5560

56-
Then open your browser to [http://localhost:8888](http://localhost:8888)
57-
58-
To persist notebook changes, mount the workspace as a volume:
59-
60-
```shell
61-
docker run -p 8888:8888 -e IONQ_API_KEY="your_api_key_here" -v $(pwd):/workspace ionq-notebooks
62-
```
61+
Open [http://localhost:8888](http://localhost:8888) in your browser.
6362

6463
---
6564

66-
## Usage
67-
68-
The samples are in the form of Jupyter notebooks, and you can view and run them using a local [Jupyter](http://jupyter.org/) installation, [VS Code](https://code.visualstudio.com/) (using the built-in Jupyter plugin), or [Google Colab](https://colab.research.google.com).
69-
70-
If you're unfamiliar with Jupyter but you're used to a traditional IDE or code editor, VS Code is probably the right choice for you.
65+
## Development
7166

72-
#### Jupyter Notebooks
67+
### Running Tests
7368

74-
1. From your terminal, navigate to this repository and run the following command from within this directory:
69+
```bash
70+
# All tests
71+
pytest tests/
7572

76-
```shell
77-
jupyter notebook
78-
```
73+
# Parallel execution
74+
pytest -n auto tests/
7975

80-
1. Once the server is started, it should automatically open your browser. In case it doesn't, you can navigate directly to it by pointing your browser at [http://localhost:8888](http://localhost:8888)
81-
1. Navigate to the location of a `.ipynb` file and open it. If you don't have a particular SDK in mind, we recommend starting with `qiskit`, as its the most commonly used library today.
76+
# Specific notebook
77+
pytest tests/test_notebooks.py::test_notebook_execution[qiskit.ipynb]
8278

83-
#### VS Code
84-
85-
1. Open the folder in VS Code and navigate to a `.ipynb` file and open it.
86-
1. If it's your first time using it, it will suggest a number of plugins that you may need to install before the notebook will be fully functional.
87-
1. At the top-right of the screen, click on `Select Kernel` and choose an appropriate Python runtime to run the notebook in.
88-
89-
#### Cloud
79+
# With custom timeout
80+
NBEXEC_TIMEOUT_SECONDS=900 pytest tests/
81+
```
9082

91-
1. Open the notebook by clicking on the ![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg) badge located in each notebook. Or open this repository in [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/ionq-samples/getting-started/HEAD)
83+
GitHub Actions automatically tests all notebooks on every push.
9284

9385
---
9486

9587
## Support
9688

97-
For support, you can submit issues or PRs in this repository. Alternatively, you can contact us at [support@ionq.com](mailto:support@ionq.com?subject=SDK%20help).
89+
Submit issues or PRs in this repository, or contact [support@ionq.com](mailto:support@ionq.com?subject=SDK%20help).

api.ipynb

Lines changed: 109 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,24 +13,97 @@
1313
},
1414
{
1515
"cell_type": "code",
16-
"execution_count": null,
16+
"execution_count": 1,
1717
"metadata": {},
1818
"outputs": [],
19-
"source": "import json\nimport time\n\nimport requests\n\nfrom helpers import get_ionq_api_key\n\n# Before you begin, get your API key from https://cloud.ionq.com/settings/keys\n\n# If your API key is stored as \"IONQ_API_KEY\" in your local environment, this\n# should find it. Otherwise you'll be prompted to enter your API key manually.\n\napi_key = get_ionq_api_key()"
19+
"source": [
20+
"import json\n",
21+
"import time\n",
22+
"\n",
23+
"import requests\n",
24+
"\n",
25+
"from helpers import get_ionq_api_key\n",
26+
"\n",
27+
"# Before you begin, get your API key from https://cloud.ionq.com/settings/keys\n",
28+
"\n",
29+
"# If your API key is stored as \"IONQ_API_KEY\" in your local environment, this\n",
30+
"# should find it. Otherwise you'll be prompted to enter your API key manually.\n",
31+
"\n",
32+
"api_key = get_ionq_api_key()\n",
33+
"\n",
34+
"# Configuration\n",
35+
"SHOTS = 100"
36+
]
2037
},
2138
{
2239
"cell_type": "code",
23-
"execution_count": null,
40+
"execution_count": 2,
2441
"metadata": {},
2542
"outputs": [],
26-
"source": "# Define helper functions for interacting with IonQ's API.\n\ndef submit_job(headers, data):\n \"\"\"Submit a quantum job to IonQ's API.\"\"\"\n url = \"https://api.ionq.co/v0.3/jobs\"\n response = requests.post(url, headers=headers, data=data)\n response_json = response.json()\n assert response.status_code == 200, f\"Error: {response_json.get('message', 'Unknown error')}\"\n return response_json[\"id\"]\n\ndef query_job(job_id, headers):\n \"\"\"Query the status of a submitted job.\"\"\"\n url = f\"https://api.ionq.co/v0.3/jobs/{job_id}\"\n response = requests.get(url, headers=headers)\n response_json = response.json()\n assert response.status_code == 200, f\"Error: {response_json.get('message', 'Unknown error')}\"\n return response_json[\"status\"]\n\ndef get_job_results(job_id, headers):\n \"\"\"Retrieve the results of a completed job.\"\"\"\n url = f\"https://api.ionq.co/v0.3/jobs/{job_id}/results\"\n response = requests.get(url, headers=headers)\n response_json = response.json()\n assert response.status_code == 200, f\"Error: {response_json.get('message', 'Unknown error')}\"\n return response_json"
43+
"source": [
44+
"# Define helper functions for interacting with IonQ's API.\n",
45+
"\n",
46+
"def submit_job(headers, data):\n",
47+
" \"\"\"Submit a quantum job to IonQ's API.\"\"\"\n",
48+
" url = \"https://api.ionq.co/v0.3/jobs\"\n",
49+
" response = requests.post(url, headers=headers, data=data)\n",
50+
" response_json = response.json()\n",
51+
" assert response.status_code == 200, f\"Error: {response_json.get('message', 'Unknown error')}\"\n",
52+
" return response_json[\"id\"]\n",
53+
"\n",
54+
"def query_job(job_id, headers):\n",
55+
" \"\"\"Query the status of a submitted job.\"\"\"\n",
56+
" url = f\"https://api.ionq.co/v0.3/jobs/{job_id}\"\n",
57+
" response = requests.get(url, headers=headers)\n",
58+
" response_json = response.json()\n",
59+
" assert response.status_code == 200, f\"Error: {response_json.get('message', 'Unknown error')}\"\n",
60+
" return response_json[\"status\"]\n",
61+
"\n",
62+
"def get_job_results(job_id, headers):\n",
63+
" \"\"\"Retrieve the results of a completed job.\"\"\"\n",
64+
" url = f\"https://api.ionq.co/v0.3/jobs/{job_id}/results\"\n",
65+
" response = requests.get(url, headers=headers)\n",
66+
" response_json = response.json()\n",
67+
" assert response.status_code == 200, f\"Error: {response_json.get('message', 'Unknown error')}\"\n",
68+
" return response_json"
69+
]
2770
},
2871
{
2972
"cell_type": "code",
30-
"execution_count": null,
73+
"execution_count": 3,
3174
"metadata": {},
3275
"outputs": [],
33-
"source": "# Set up the request headers and define our circuit.\n# This circuit creates a Bell state with two qubits using IonQ's native format.\n\nheaders = {\n \"Authorization\": f\"apiKey {api_key}\",\n \"Content-Type\": \"application/json\",\n}\n\ndata = {\n \"name\": \"API Example Circuit\",\n \"shots\": 100,\n \"target\": \"simulator\",\n \"input\": {\n \"format\": \"ionq.circuit.v0\",\n \"gateset\": \"qis\",\n \"qubits\": 2,\n \"circuit\": [\n {\n \"gate\": \"h\",\n \"target\": 0\n },\n {\n \"gate\": \"cnot\",\n \"control\": 0,\n \"target\": 1\n }\n ]\n }\n}\n"
76+
"source": [
77+
"# Set up the request headers and define our circuit.\n",
78+
"# This circuit creates a Bell state with two qubits using IonQ's native format.\n",
79+
"\n",
80+
"headers = {\n",
81+
" \"Authorization\": f\"apiKey {api_key}\",\n",
82+
" \"Content-Type\": \"application/json\",\n",
83+
"}\n",
84+
"\n",
85+
"data = {\n",
86+
" \"name\": \"API Example Circuit\",\n",
87+
" \"shots\": SHOTS,\n",
88+
" \"target\": \"simulator\",\n",
89+
" \"input\": {\n",
90+
" \"format\": \"ionq.circuit.v0\",\n",
91+
" \"gateset\": \"qis\",\n",
92+
" \"qubits\": 2,\n",
93+
" \"circuit\": [\n",
94+
" {\n",
95+
" \"gate\": \"h\",\n",
96+
" \"target\": 0\n",
97+
" },\n",
98+
" {\n",
99+
" \"gate\": \"cnot\",\n",
100+
" \"control\": 0,\n",
101+
" \"target\": 1\n",
102+
" }\n",
103+
" ]\n",
104+
" }\n",
105+
"}\n"
106+
]
34107
},
35108
{
36109
"cell_type": "markdown",
@@ -62,10 +135,34 @@
62135
},
63136
{
64137
"cell_type": "code",
65-
"execution_count": null,
138+
"execution_count": 4,
66139
"metadata": {},
67-
"outputs": [],
68-
"source": "# Now we'll send the job to our backend for processing.\n\njob_id = submit_job(headers, json.dumps(data))\n\n# And wait for the job to complete.\n\nstatus = \"ready\"\nwhile status != \"completed\":\n time.sleep(1) # Wait for 1 second before querying again.\n status = query_job(job_id, headers)\n\n# Once the job has completed, we can retrieve and display the results.\n\nresults = get_job_results(job_id, headers)\nprint(results)"
140+
"outputs": [
141+
{
142+
"name": "stdout",
143+
"output_type": "stream",
144+
"text": [
145+
"{'0': 0.5, '3': 0.5}\n"
146+
]
147+
}
148+
],
149+
"source": [
150+
"# Now we'll send the job to our backend for processing.\n",
151+
"\n",
152+
"job_id = submit_job(headers, json.dumps(data))\n",
153+
"\n",
154+
"# And wait for the job to complete.\n",
155+
"\n",
156+
"status = \"ready\"\n",
157+
"while status != \"completed\":\n",
158+
" time.sleep(1) # Wait for 1 second before querying again.\n",
159+
" status = query_job(job_id, headers)\n",
160+
"\n",
161+
"# Once the job has completed, we can retrieve and display the results.\n",
162+
"\n",
163+
"results = get_job_results(job_id, headers)\n",
164+
"print(results)"
165+
]
69166
},
70167
{
71168
"cell_type": "markdown",
@@ -94,9 +191,8 @@
94191
"nbconvert_exporter": "python",
95192
"pygments_lexer": "ipython3",
96193
"version": "3.14.2"
97-
},
98-
"orig_nbformat": 4
194+
}
99195
},
100196
"nbformat": 4,
101-
"nbformat_minor": 2
102-
}
197+
"nbformat_minor": 4
198+
}

cirq.ipynb

Lines changed: 49 additions & 10 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)