Skip to content

Commit

Permalink
Merge branch 'issues/433_plotting_isinstance_fail' into issues/435_ma…
Browse files Browse the repository at this point in the history
…pping_pt_to_same_channel
  • Loading branch information
terrorfisch committed Mar 12, 2019
2 parents 9153942 + a0d4d09 commit cc7410a
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 6 deletions.
5 changes: 5 additions & 0 deletions ReleaseNotes.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## pending/current ##

- General:
- Add utility function `qupulse.utils.types.has_type_interface` and use it to circumvent autoreload triggered isinstance fails

## 0.3 ##

- General:
Expand Down
13 changes: 7 additions & 6 deletions qupulse/pulses/plotting.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import operator
import itertools

from qupulse.utils.types import ChannelID, MeasurementWindow
from qupulse.utils.types import ChannelID, MeasurementWindow, has_type_interface
from qupulse.pulses.pulse_template import PulseTemplate
from qupulse.pulses.parameters import Parameter
from qupulse._program.waveforms import Waveform
Expand Down Expand Up @@ -130,15 +130,16 @@ def render(program: Union[AbstractInstructionBlock, Loop],
measurements is a sequence of all measurements where each measurement is represented by a tuple
(name, start_time, duration).
"""

if isinstance(program, AbstractInstructionBlock):
if has_type_interface(program, Loop):
return _render_loop(program, sample_rate=sample_rate,
render_measurements=render_measurements, time_slice=time_slice)
elif has_type_interface(program, AbstractInstructionBlock):
warnings.warn("InstructionBlock API is deprecated", DeprecationWarning)
if time_slice is not None:
raise ValueError("Keyword argument time_slice is not supported when rendering instruction blocks")
return _render_instruction_block(program, sample_rate=sample_rate, render_measurements=render_measurements)
elif isinstance(program, Loop):
return _render_loop(program, sample_rate=sample_rate,
render_measurements=render_measurements, time_slice=time_slice)
else:
raise ValueError('Cannot render an object of type %s', type(program))


def _render_instruction_block(sequence: AbstractInstructionBlock,
Expand Down
5 changes: 5 additions & 0 deletions qupulse/utils/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,8 @@ class HashableNumpyArray(numpy.ndarray):
"""
def __hash__(self):
return hash(self.tobytes())


def has_type_interface(obj: typing.Any, type_obj: typing.Type) -> bool:
"""Return true if all public attributes of the class are attribues of the object"""
return set(dir(obj)) >= {attr for attr in dir(type_obj) if not attr.startswith('_')}
44 changes: 44 additions & 0 deletions tests/pulses/plotting_tests.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import unittest
from unittest import mock
import sys
import importlib

import numpy

from qupulse.pulses.plotting import PlottingNotPossibleException, render, iter_waveforms, iter_instruction_block, plot
Expand Down Expand Up @@ -304,3 +308,43 @@ def test(self) -> None:
exception = PlottingNotPossibleException(t)
self.assertIs(t, exception.pulse)
self.assertIsInstance(str(exception), str)


class PlottingIsinstanceTests(unittest.TestCase):
@unittest.skip("Breaks other tests")
def test_bug_422(self):
import matplotlib
matplotlib.use('svg') # use non-interactive backend so that test does not fail on travis

to_reload = ['qupulse._program._loop',
'qupulse.pulses.pulse_template',
'qupulse.pulses.table_pulse_template']

with mock.patch.dict(sys.modules, sys.modules.copy()):
for module in to_reload:
sys.modules.pop(module, None)
for module in to_reload:
sys.modules[module] = importlib.reload(importlib.import_module(module))

from qupulse.pulses.table_pulse_template import TablePulseTemplate

pt = TablePulseTemplate({'X': [(0, 1), (1, 1)]})

plot(pt, parameters={})

def test_bug_422_mock(self):
pt = TablePulseTemplate({'X': [(0, 1), (100, 1)]})
program = pt.create_program()

mock_program = mock.Mock(spec=dir(program))

for attr in dir(Loop):
if not attr.endswith('_'):
setattr(mock_program, attr, getattr(program, attr))
mock_program.__len__ = lambda x: 1
mock_program.__iter__ = lambda x: iter(program)
mock_program.__getitem__ = lambda x, idx: program[idx]

self.assertNotIsInstance(mock_program, Loop)

render(mock_program, sample_rate=1)

0 comments on commit cc7410a

Please sign in to comment.