Skip to content

Commit b4b839e

Browse files
cclaussTakishima
andauthored
Context Manager: with flushing(MainEngine()) as eng: (#449)
* Context Manager: with flushing(MainEngine()) as eng: Simplify the creation, use, and flushing of any Engine using a Python context manager. When exiting the `with` block, the engine is _automatically_ flushed. Modeled after https://docs.python.org/3/library/contextlib.html#contextlib.closing ```python from projectq import MainEngine, flushing # import the main compiler engine from projectq.ops import ( H, Measure, ) # import the operations we want to perform (Hadamard and measurement) with flushing(MainEngine()) as eng: # create a default compiler (the back-end is a simulator) qubit = eng.allocate_qubit() # allocate a quantum register with 1 qubit H | qubit # apply a Hadamard gate Measure | qubit # measure the qubit # This line is no longer required... eng.flush() print(f"Measured {int(qubit)}") # converting a qubit to int or bool gives access to the measurement result * Add tests * Run linters/formatters on code * Fix isort comment pragmas * Really fix isort issues in cengines/__init__.py Co-authored-by: Damien Nguyen <ngn.damien@gmail.com>
1 parent b768038 commit b4b839e

File tree

3 files changed

+67
-0
lines changed

3 files changed

+67
-0
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [Unreleased]
9+
10+
### Added
11+
12+
- Python context manager `with flusing(MainEngine()) as eng:`
13+
814
## [v0.8.0] - 2022-10-18
915

1016
### Added

projectq/cengines/__init__.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,14 @@
1414

1515
"""ProjectQ module containing all compiler engines."""
1616

17+
from contextlib import contextmanager
18+
1719
from ._basics import BasicEngine, ForwarderEngine, LastEngineException # isort:skip
1820
from ._cmdmodifier import CommandModifier # isort:skip
1921
from ._basicmapper import BasicMapperEngine # isort:skip
2022

23+
# isort: split
24+
2125
from ._ibm5qubitmapper import IBM5QubitMapper
2226
from ._linearmapper import LinearMapper, return_swap_depth
2327
from ._main import MainEngine, NotYetMeasuredError, UnsupportedEngineError
@@ -33,3 +37,22 @@
3337
from ._tagremover import TagRemover
3438
from ._testengine import CompareEngine, DummyEngine
3539
from ._twodmapper import GridMapper
40+
41+
42+
@contextmanager
43+
def flushing(engine):
44+
"""
45+
Context manager to flush the given engine at the end of the 'with' context block.
46+
47+
Example:
48+
with flushing(MainEngine()) as eng:
49+
qubit = eng.allocate_qubit()
50+
...
51+
52+
Calling 'eng.flush()' is no longer needed because the engine will be flushed at the
53+
end of the 'with' block even if an exception has been raised within that block.
54+
"""
55+
try:
56+
yield engine
57+
finally:
58+
engine.flush()
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Copyright 2017 ProjectQ-Framework (www.projectq.ch)
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
"""Tests for projectq.cengines.__init__.py."""
15+
16+
from unittest.mock import MagicMock
17+
18+
from projectq.cengines import DummyEngine, flushing
19+
20+
21+
def test_with_flushing():
22+
"""Test with flushing() as eng:"""
23+
with flushing(DummyEngine()) as engine:
24+
engine.flush = MagicMock()
25+
assert engine.flush.call_count == 0
26+
assert engine.flush.call_count == 1
27+
28+
29+
def test_with_flushing_with_exception():
30+
"""Test with flushing() as eng: with an exception raised in the 'with' block."""
31+
try:
32+
with flushing(DummyEngine()) as engine:
33+
engine.flush = MagicMock()
34+
assert engine.flush.call_count == 0
35+
raise ValueError("An exception is raised in the 'with' block")
36+
except ValueError:
37+
pass
38+
assert engine.flush.call_count == 1

0 commit comments

Comments
 (0)