diff --git a/test/test_editor_base_panel.py b/test/test_editor_base_panel.py new file mode 100644 index 00000000..538fa524 --- /dev/null +++ b/test/test_editor_base_panel.py @@ -0,0 +1,55 @@ +# zxlive - An interactive tool for the ZX calculus +# Copyright (C) 2023 - Aleks Kissinger +# +# 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 + +# http://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. + + +import pytest + +from zxlive.editor_base_panel import string_to_phase +from fractions import Fraction + + +def test_string_to_phase(): + # Test empty input clears the phase. + assert string_to_phase('', None, 'fraction') == Fraction(0) + + # Test different ways of specifying integer multiples of pi. + assert string_to_phase('3', None, 'fraction') == Fraction(3) + assert string_to_phase('3pi', None, 'fraction') == Fraction(3) + assert string_to_phase('3*pi', None, 'fraction') == Fraction(3) + assert string_to_phase('pi*3', None, 'fraction') == Fraction(3) + + # Test different ways of specifying fractions. + assert string_to_phase('pi/2', None, 'fraction') == Fraction(1,2) + assert string_to_phase('-pi/2', None, 'fraction') == Fraction(-1,2) + assert string_to_phase('5/2', None, 'fraction') == Fraction(5,2) + assert string_to_phase('5pi/2', None, 'fraction') == Fraction(5,2) + assert string_to_phase('5*pi/2', None, 'fraction') == Fraction(5,2) + assert string_to_phase('pi*5/2', None, 'fraction') == Fraction(5,2) + assert string_to_phase('5/2pi', None, 'fraction') == Fraction(5,2) + assert string_to_phase('5/2*pi', None, 'fraction') == Fraction(5,2) + assert string_to_phase('5/pi*2', None, 'fraction') == Fraction(5,2) + + # Test different ways of specifying floats. + assert string_to_phase('5.5', None, 'fraction') == Fraction(11,2) + assert string_to_phase('5.5pi', None, 'fraction') == Fraction(11,2) + assert string_to_phase('25e-1', None, 'fraction') == Fraction(5,2) + assert string_to_phase('5.5*pi', None, 'fraction') == Fraction(11,2) + assert string_to_phase('pi*5.5', None, 'fraction') == Fraction(11,2) + + # TODO: test complex and polynomial input. + + # Test bad input. + with pytest.raises(ValueError): + string_to_phase('bad input', None, 'fraction') diff --git a/zxlive/editor_base_panel.py b/zxlive/editor_base_panel.py index b46b3f91..e7461741 100644 --- a/zxlive/editor_base_panel.py +++ b/zxlive/editor_base_panel.py @@ -1,6 +1,7 @@ from __future__ import annotations import copy +import re from enum import Enum from fractions import Fraction from typing import Callable, Iterator, TypedDict @@ -161,16 +162,20 @@ def vert_double_clicked(self, v: VT) -> None: if graph.type(v) == VertexType.BOUNDARY or vertex_is_w(graph.type(v)): return None + if graph.type(v) == VertexType.Z_BOX: + fraction_or_complex = 'complex' + prompt = "Enter desired phase value (complex value):" + else: + fraction_or_complex = 'fraction' + prompt = "Enter desired phase value (in units of pi):" + input_, ok = QInputDialog.getText( - self, "Input Dialog", "Enter Desired Phase Value:" + self, "Change Phase", prompt ) if not ok: return None try: - if graph.type(v) == VertexType.Z_BOX: - new_phase = string_to_phase(input_, self._new_var, 'complex') - else: - new_phase = string_to_phase(input_, self._new_var, 'fraction') + new_phase = string_to_phase(input_, self._new_var, fraction_or_complex) except ValueError: show_error_msg("Wrong Input Type", "Please enter a valid input (e.g. 1/2, 2)") return None @@ -352,7 +357,7 @@ def string_to_phase(string: str, new_var, fraction_or_complex='fraction'): try: if fraction_or_complex == 'fraction': s = string.lower().replace(' ', '') - s = s.replace('\u03c0', '').replace('pi', '') + s = re.sub('\\*?(pi|\u04c0)\\*?', '', s) if '.' in s or 'e' in s: return Fraction(float(s)) elif '/' in s: @@ -367,5 +372,7 @@ def string_to_phase(string: str, new_var, fraction_or_complex='fraction'): else: return complex(string) except ValueError: - return parse(string, new_var) - + try: + return parse(string, new_var) + except Exception as e: + raise ValueError