Skip to content

Commit

Permalink
Merge pull request #394 from qutech/requirements
Browse files Browse the repository at this point in the history
Added requirements.txt + some additional minor changes to testing
  • Loading branch information
terrorfisch authored Sep 28, 2018
2 parents 7067307 + f4982a7 commit 002072a
Show file tree
Hide file tree
Showing 9 changed files with 47 additions and 196 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ before_install:
- source activate test-environment
- pip install coverage coveralls
install:
- pip install -r requirements.txt
- pip install .$INSTALL_EXTRAS
script:
- "coverage run --source=qupulse --rcfile=coverage.ini setup.py test"
Expand Down
10 changes: 3 additions & 7 deletions qupulse/utils/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,6 @@
import fractions
import warnings

try:
import gmpy2
except ImportError:
gmpy2 = None

import numpy

__all__ = ["MeasurementWindow", "ChannelID", "HashableNumpyArray", "TimeType", "time_from_float", "DocStringABCMeta",
Expand All @@ -19,13 +14,14 @@
ChannelID = typing.Union[str, int]


if gmpy2:
try:
import gmpy2
TimeType = gmpy2.mpq

def time_from_float(time: float, absolute_error: float=1e-12) -> TimeType:
# gmpy2 is at least an order of magnitude faster than fractions.Fraction
return gmpy2.mpq(gmpy2.f2q(time, absolute_error))
else:
except ImportError:
warnings.warn('gmpy2 not found. Using fractions.Fraction as fallback. Install gmpy2 for better performance.')

TimeType = fractions.Fraction
Expand Down
16 changes: 15 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1,15 @@
.
cached-property==1.5.1
matplotlib==3.0.0
numpy==1.15.2
PyVISA==1.9.1
sympy==1.3
gmpy2==2.0.8

certifi==2018.8.24
cycler==0.10.0
kiwisolver==1.0.1
mpmath==1.0.0
pyparsing==2.2.1
python-dateutil==2.7.3
six==1.11.0
wincertstore==0.2
1 change: 0 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ def extract_version(version_file):
package_dir={'qupulse': 'qupulse', 'qctoolkit': 'qctoolkit'},
packages=packages,
python_requires='>=3.4',
tests_require=['pytest'],
install_requires=['sympy>=1.1.1', 'numpy', 'cached_property'] + requires_typing,
extras_require={
'plotting': ['matplotlib'],
Expand Down
12 changes: 0 additions & 12 deletions tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,2 @@
import matplotlib
matplotlib.use('Agg')

__all__ = [
'pulses',
'qcmatlab',
'utils',
'comparable_tests',
'format_tests',
'pyflakes_syntax_tests',
'serialization_dummies',
'serialization_tests',
'backward_compatibility'
]
115 changes: 0 additions & 115 deletions tests/annotation_tests.py

This file was deleted.

16 changes: 0 additions & 16 deletions tests/format_tests.py

This file was deleted.

19 changes: 0 additions & 19 deletions tests/pulses/__init__.py
Original file line number Diff line number Diff line change
@@ -1,19 +0,0 @@
__all__ = [
'branch_pulse_template_tests',
'conditions_tests',
'function_pulse_tests',
'instructions_tests',
'interpolation_tests',
'loop_pulse_template_tests',
'multi_channel_pulse_template_tests',
'parameters_tests',
'plotting_tests',
'mapping_pulse_template_tests.py',
'pulse_template_tests',
'repetition_pulse_template_tests',
'sample_pulse_generator',
'sequence_pulse_template_tests',
'sequencing_dummies',
'sequencing_tests',
'table_pulse_template_tests'
]
53 changes: 28 additions & 25 deletions tests/utils/time_type_test.py → tests/utils/time_type_tests.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import sys
import unittest
import os
import builtins
import contextlib
import importlib
import fractions
Expand All @@ -14,23 +14,29 @@
import qupulse.utils.types as qutypes


def mock_missing_gmpy2(exit_stack: contextlib.ExitStack):
if os.path.exists('gmpy2.py'):
raise RuntimeError('Cannot mock missing gmpy2 due to existing file')
@contextlib.contextmanager
def mock_missing_module(module_name: str):
exit_stack = contextlib.ExitStack()

with open('gmpy2.py', 'w') as gmpy_file:
exit_stack.callback(os.remove, 'gmpy2.py')
if module_name in sys.modules:
# temporarily remove gmpy2 from the imported modules

gmpy_file.write("raise ImportError()")
temp_modules = sys.modules.copy()
del temp_modules[module_name]
exit_stack.enter_context(mock.patch.dict(sys.modules, temp_modules))

if 'gmpy2' in sys.modules:
modules_patcher = mock.patch.dict(sys.modules,
values=((name, module)
for name, module in sys.modules.items()
if name != 'gmpy2'),
clear=True)
modules_patcher.__enter__()
exit_stack.push(modules_patcher)
original_import = builtins.__import__

def mock_import(name, *args, **kwargs):
if name == module_name:
raise ImportError(name)
else:
return original_import(name, *args, **kwargs)

exit_stack.enter_context(mock.patch('builtins.__import__', mock_import))

with exit_stack:
yield


class TestTimeType(unittest.TestCase):
Expand All @@ -39,25 +45,22 @@ class TestTimeType(unittest.TestCase):
@property
def fallback_qutypes(self):
if not self._fallback_qutypes:
exit_stack = contextlib.ExitStack()

with exit_stack:

if gmpy2:
# create a local file that raises ImportError on import
mock_missing_gmpy2(exit_stack)

if gmpy2:
with mock_missing_module('gmpy2'):
self._fallback_qutypes = importlib.reload(qutypes)

else:
self._fallback_qutypes = qutypes
else:
self._fallback_qutypes = qutypes
return self._fallback_qutypes

def test_fraction_fallback(self):
self.assertIs(fractions.Fraction, self.fallback_qutypes.TimeType)

@unittest.skipIf(gmpy2 is None, "gmpy2 not available.")
def test_default_time_from_float(self):
# assert mocking did no permanent damage
self.assertIs(gmpy2.mpq, qutypes.TimeType)

self.assertEqual(qutypes.time_from_float(123/931), gmpy2.mpq(123, 931))

self.assertEqual(qutypes.time_from_float(1000000/1000001, 1e-5), gmpy2.mpq(1))
Expand Down

0 comments on commit 002072a

Please sign in to comment.