From 3de7cb5053b8b0fdbae9988135c4d764478d6cec Mon Sep 17 00:00:00 2001 From: Peter Solodov Date: Tue, 20 Feb 2024 11:35:06 -0500 Subject: [PATCH 1/7] allow action selections to be modified This change adds a function to get multiple user inputs, each with its own prompt function. Once all inputs have been collected, user gets a chance to confirm selection by providing empty input (press enter) or enter "r" to select again. --- .gitignore | 2 + unitary/examples/quantum_rpg/battle.py | 19 +++++---- unitary/examples/quantum_rpg/battle_test.py | 30 ++++++++++---- unitary/examples/quantum_rpg/input_helpers.py | 31 +++++++++++++-- .../quantum_rpg/input_helpers_test.py | 39 +++++++++++++++++-- 5 files changed, 98 insertions(+), 23 deletions(-) diff --git a/.gitignore b/.gitignore index 00b93bc6..b8d0da42 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,5 @@ docs/generated # Notebook formatting script. nbformat + +build \ No newline at end of file diff --git a/unitary/examples/quantum_rpg/battle.py b/unitary/examples/quantum_rpg/battle.py index e859bc18..da53b53f 100644 --- a/unitary/examples/quantum_rpg/battle.py +++ b/unitary/examples/quantum_rpg/battle.py @@ -143,19 +143,22 @@ def take_player_turn(self): else: break if action in current_player.actions(): - monster = ( - input_helpers.get_user_input_number( + monster, qubit = input_helpers.get_multiple_user_inputs( + self.get_user_input, + lambda: input_helpers.get_user_input_number( self.get_user_input, "Which enemy number: ", max_number=len(self.enemy_side), file=self.file, - ) - - 1 - ) - selected_monster = self.enemy_side[monster] - qubit = input_helpers.get_user_input_number( - self.get_user_input, "Which enemy qubit number: ", file=self.file + ), + lambda: input_helpers.get_user_input_number( + self.get_user_input, + "Which enemy qubit number: ", + file=self.file + ), + file=self.file ) + selected_monster = self.enemy_side[monster - 1] qubit_name = selected_monster.quantum_object_name(qubit) if qubit_name in selected_monster.active_qubits(): res = actions[action](selected_monster, qubit) diff --git a/unitary/examples/quantum_rpg/battle_test.py b/unitary/examples/quantum_rpg/battle_test.py index 98f2f084..a1c4f3a3 100644 --- a/unitary/examples/quantum_rpg/battle_test.py +++ b/unitary/examples/quantum_rpg/battle_test.py @@ -23,7 +23,7 @@ def test_battle(): c = classes.Analyst("Aaronson") e = npcs.Observer("watcher") state = game_state.GameState( - party=[c], user_input=["m", "1", "1"], file=io.StringIO() + party=[c], user_input=["m", "1", "1", ""], file=io.StringIO() ) b = battle.Battle(state, [e]) b.take_player_turn() @@ -39,6 +39,8 @@ def test_battle(): m) Measure enemy qubit. q) Read Quantopedia. ?) Help. +[enter]) Confirm selection. +r) Select again. """.strip() ) @@ -47,7 +49,7 @@ def test_bad_monster(): c = classes.Analyst("Aaronson") e = npcs.Observer("watcher") state = game_state.GameState( - party=[c], user_input=["m", "2", "1", "1"], file=io.StringIO() + party=[c], user_input=["m", "2", "1", "1", ""], file=io.StringIO() ) b = battle.Battle(state, [e]) b.take_player_turn() @@ -63,6 +65,8 @@ def test_bad_monster(): q) Read Quantopedia. ?) Help. Invalid number selected. +[enter]) Confirm selection. +r) Select again. """.strip() ) @@ -78,7 +82,7 @@ def test_higher_level_players(): w = npcs.Observer("watcher") w2 = npcs.Observer("watcher") state = game_state.GameState( - [c, e], user_input=["m", "1", "1", "h", "2", "1"], file=io.StringIO() + [c, e], user_input=["m", "1", "1", "", "h", "2", "1", ""], file=io.StringIO() ) b = battle.Battle(state, [w, w2]) b.take_player_turn() @@ -96,6 +100,8 @@ def test_higher_level_players(): s) Sample enemy qubit. q) Read Quantopedia. ?) Help. +[enter]) Confirm selection. +r) Select again. ------------------------------------------------------------ Aaronson Analyst 1) watcher Observer 3QP (0|1> 0|0> 3?) 1QP (0|1> 1|0> 0?) *DOWN* @@ -107,6 +113,8 @@ def test_higher_level_players(): x) Attack with X gate. q) Read Quantopedia. ?) Help. +[enter]) Confirm selection. +r) Select again. """.strip() ) @@ -138,7 +146,7 @@ def test_battle_loop(): c = classes.Analyst("Aaronson") e = npcs.Observer("watcher") state = game_state.GameState( - party=[c], user_input=["m", "1", "1"], file=io.StringIO() + party=[c], user_input=["m", "1", "1", ""], file=io.StringIO() ) b = battle.Battle(state, [e]) assert b.loop() == battle.BattleResult.PLAYERS_WON @@ -153,6 +161,8 @@ def test_battle_loop(): m) Measure enemy qubit. q) Read Quantopedia. ?) Help. +[enter]) Confirm selection. +r) Select again. ------------------------------------------------------------ Battle Summary @@ -167,7 +177,7 @@ def test_battle_help(): c = classes.Analyst("Aaronson") e = npcs.Observer("watcher") state = game_state.GameState( - party=[c], user_input=["?", "m", "1", "1"], file=io.StringIO() + party=[c], user_input=["?", "m", "1", "1", ""], file=io.StringIO() ) b = battle.Battle(state, [e]) assert b.loop() == battle.BattleResult.PLAYERS_WON @@ -186,6 +196,8 @@ def test_battle_help(): into the |0> state or |1> state with a probability based on its amplitude. Try to measure the enemy qubits as |0> to defeat them. +[enter]) Confirm selection. +r) Select again. ------------------------------------------------------------ Battle Summary @@ -200,7 +212,7 @@ def test_read_quantopedia_not_known(): c = classes.Analyst("Aaronson") e = npcs.Observer("watcher") state = game_state.GameState( - party=[c], user_input=["q", "m", "1", "1"], file=io.StringIO() + party=[c], user_input=["q", "m", "1", "1", ""], file=io.StringIO() ) b = battle.Battle(state, [e]) assert b.loop() == battle.BattleResult.PLAYERS_WON @@ -216,6 +228,8 @@ def test_read_quantopedia_not_known(): q) Read Quantopedia. ?) Help. You do not have information on Observer yet. +[enter]) Confirm selection. +r) Select again. ------------------------------------------------------------ Battle Summary @@ -230,7 +244,7 @@ def test_read_quantopedia(): c = classes.Analyst("Aaronson") e = npcs.Observer("watcher") state = game_state.GameState( - party=[c], user_input=["q", "m", "1", "1"], file=io.StringIO() + party=[c], user_input=["q", "m", "1", "1", ""], file=io.StringIO() ) state.set_quantopedia(1) b = battle.Battle(state, [e]) @@ -248,6 +262,8 @@ def test_read_quantopedia(): ?) Help. Observers are known to frequent quantum events. They will measure qubits in order to find out their values. +[enter]) Confirm selection. +r) Select again. ------------------------------------------------------------ Battle Summary diff --git a/unitary/examples/quantum_rpg/input_helpers.py b/unitary/examples/quantum_rpg/input_helpers.py index d9d52a3e..d8694c1d 100644 --- a/unitary/examples/quantum_rpg/input_helpers.py +++ b/unitary/examples/quantum_rpg/input_helpers.py @@ -2,7 +2,7 @@ from typing import Callable, Optional, Sequence, TextIO import sys -import unitary.examples.quantum_rpg.qaracter as qaracter +from unitary.examples.quantum_rpg import qaracter _USER_INPUT = Callable[[str], str] _INVALID_MESSAGE = "Invalid number selected." @@ -26,9 +26,9 @@ def get_user_input_number( get_user_input: _USER_INPUT, message: str = "", max_number: Optional[int] = None, - invalid_message: Optional[str] = _INVALID_MESSAGE, + invalid_message: str = _INVALID_MESSAGE, file: TextIO = sys.stdout, -): +) -> int: """Helper to get a valid number from the user. This will only accept valid numbers from the user from 1 to max_number. @@ -53,9 +53,32 @@ def get_user_input_number( print("number out of range", file=file) +def get_multiple_user_inputs( + get_user_input: _USER_INPUT, + *prompts: Sequence[Callable[[], int] | Callable[[], str]], + file: TextIO = sys.stdout, +) -> Sequence[int | str]: + """Runs multiple number or string prompts and returns their results. + + After all inputs have been provided the last prompt asks for confirmation if + user happy with inputs, and allows to restart the sequence and change + inputs. + """ + while True: + inputs = [p() for p in prompts] + print("[enter]) Confirm selection.", file=file) + print("r) Select again.", file=file) + while True: + match get_user_input("Choose your action: "): + case "r": + break + case "": + return inputs + + def get_user_input_qaracter_name( get_user_input: _USER_INPUT, - qaracter_type: Optional[str] = "a new qaracter", + qaracter_type: str = "a new qaracter", file: TextIO = sys.stdout, ): while True: diff --git a/unitary/examples/quantum_rpg/input_helpers_test.py b/unitary/examples/quantum_rpg/input_helpers_test.py index 01ebd015..7beab454 100644 --- a/unitary/examples/quantum_rpg/input_helpers_test.py +++ b/unitary/examples/quantum_rpg/input_helpers_test.py @@ -1,7 +1,8 @@ -import pytest import io -import unitary.examples.quantum_rpg.input_helpers as input_helpers +import pytest + +from unitary.examples.quantum_rpg import input_helpers def test_get_user_input_function(): @@ -38,8 +39,38 @@ def test_get_user_input_number_invalid(): def test_get_user_input_number_max(): - get_input = input_helpers.get_user_input_function(["0", "-1", "a", "7", "3"]) + get_input = input_helpers.get_user_input_function( + ["0", "-1", "a", "7", "3"]) output = io.StringIO() assert ( - input_helpers.get_user_input_number(get_input, file=output, max_number=4) == 3 + input_helpers.get_user_input_number( + get_input, file=output, max_number=4) == 3 + ) + + +def test_get_multiple_user_inputs(): + get_input = input_helpers.get_user_input_function( + ["1", "2", "r", "3", "1", ""], ) + output = io.StringIO() + + def p1(): + return input_helpers.get_user_input_number( + get_input, + max_number=4, + file=output, + ) + + def p2(): + return input_helpers.get_user_input_number( + get_input, + max_number=4, + file=output, + ) + + assert input_helpers.get_multiple_user_inputs( + get_input, + p1, + p2, + file=output, + ) == [3, 1] From 04a8765116b683e57466ad53f8fa539df5729945 Mon Sep 17 00:00:00 2001 From: Peter Solodov Date: Tue, 20 Feb 2024 11:46:18 -0500 Subject: [PATCH 2/7] match statement is not available yet in unitary tests --- unitary/examples/quantum_rpg/input_helpers.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/unitary/examples/quantum_rpg/input_helpers.py b/unitary/examples/quantum_rpg/input_helpers.py index d8694c1d..a6d670f6 100644 --- a/unitary/examples/quantum_rpg/input_helpers.py +++ b/unitary/examples/quantum_rpg/input_helpers.py @@ -69,11 +69,11 @@ def get_multiple_user_inputs( print("[enter]) Confirm selection.", file=file) print("r) Select again.", file=file) while True: - match get_user_input("Choose your action: "): - case "r": - break - case "": - return inputs + a = get_user_input("Choose your action: ") + if a == "r": + break + if a == "": + return inputs def get_user_input_qaracter_name( From aa5db22ec12477f1cf9c0d7698cb65d140be49f3 Mon Sep 17 00:00:00 2001 From: Peter Solodov Date: Tue, 20 Feb 2024 11:50:27 -0500 Subject: [PATCH 3/7] fixed lint warnings --- unitary/examples/quantum_rpg/battle.py | 4 ++-- unitary/examples/quantum_rpg/input_helpers_test.py | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/unitary/examples/quantum_rpg/battle.py b/unitary/examples/quantum_rpg/battle.py index da53b53f..2aca9391 100644 --- a/unitary/examples/quantum_rpg/battle.py +++ b/unitary/examples/quantum_rpg/battle.py @@ -154,9 +154,9 @@ def take_player_turn(self): lambda: input_helpers.get_user_input_number( self.get_user_input, "Which enemy qubit number: ", - file=self.file + file=self.file, ), - file=self.file + file=self.file, ) selected_monster = self.enemy_side[monster - 1] qubit_name = selected_monster.quantum_object_name(qubit) diff --git a/unitary/examples/quantum_rpg/input_helpers_test.py b/unitary/examples/quantum_rpg/input_helpers_test.py index 7beab454..21a12fa6 100644 --- a/unitary/examples/quantum_rpg/input_helpers_test.py +++ b/unitary/examples/quantum_rpg/input_helpers_test.py @@ -43,8 +43,7 @@ def test_get_user_input_number_max(): ["0", "-1", "a", "7", "3"]) output = io.StringIO() assert ( - input_helpers.get_user_input_number( - get_input, file=output, max_number=4) == 3 + input_helpers.get_user_input_number(get_input, file=output, max_number=4) == 3 ) From 49ab1947c8c08d1cd08de6772dc3d90e5c83dd78 Mon Sep 17 00:00:00 2001 From: Peter Solodov Date: Tue, 20 Feb 2024 11:52:45 -0500 Subject: [PATCH 4/7] and another lint warning --- unitary/examples/quantum_rpg/input_helpers.py | 1 + 1 file changed, 1 insertion(+) diff --git a/unitary/examples/quantum_rpg/input_helpers.py b/unitary/examples/quantum_rpg/input_helpers.py index a6d670f6..125d1dac 100644 --- a/unitary/examples/quantum_rpg/input_helpers.py +++ b/unitary/examples/quantum_rpg/input_helpers.py @@ -1,4 +1,5 @@ """Functions for safe and user-friendly input.""" + from typing import Callable, Optional, Sequence, TextIO import sys From 67fe0dd1e818c2be4dd5b5a19b770c96f2bd9196 Mon Sep 17 00:00:00 2001 From: Peter Solodov Date: Tue, 5 Mar 2024 10:53:26 +0100 Subject: [PATCH 5/7] Finished support for confirming selection: - fixed type annotations to support python 3.9 - fixed remaining broken tests - reformatted changed files --- .../examples/quantum_rpg/encounter_test.py | 7 ++++-- unitary/examples/quantum_rpg/input_helpers.py | 8 +++---- .../quantum_rpg/input_helpers_test.py | 3 +-- .../examples/quantum_rpg/main_loop_test.py | 22 ++++++++++++++----- 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/unitary/examples/quantum_rpg/encounter_test.py b/unitary/examples/quantum_rpg/encounter_test.py index 25687d8b..a67f78b0 100644 --- a/unitary/examples/quantum_rpg/encounter_test.py +++ b/unitary/examples/quantum_rpg/encounter_test.py @@ -13,11 +13,12 @@ # limitations under the License. import io + import unitary.alpha as alpha import unitary.examples.quantum_rpg.battle as battle import unitary.examples.quantum_rpg.classes as classes -import unitary.examples.quantum_rpg.game_state as game_state import unitary.examples.quantum_rpg.encounter as encounter +import unitary.examples.quantum_rpg.game_state as game_state import unitary.examples.quantum_rpg.npcs as npcs import unitary.examples.quantum_rpg.xp_utils as xp_utils @@ -38,7 +39,7 @@ def test_encounter(): c = classes.Analyst("Aaronson") o = npcs.Observer("watcher") state = game_state.GameState( - party=[c], user_input=["m", "1", "1"], file=io.StringIO() + party=[c], user_input=["m", "1", "1", ""], file=io.StringIO() ) e = encounter.Encounter([o]) @@ -56,6 +57,8 @@ def test_encounter(): m) Measure enemy qubit. q) Read Quantopedia. ?) Help. +[enter]) Confirm selection. +r) Select again. """.strip() ) diff --git a/unitary/examples/quantum_rpg/input_helpers.py b/unitary/examples/quantum_rpg/input_helpers.py index 125d1dac..b67557ab 100644 --- a/unitary/examples/quantum_rpg/input_helpers.py +++ b/unitary/examples/quantum_rpg/input_helpers.py @@ -1,8 +1,8 @@ """Functions for safe and user-friendly input.""" -from typing import Callable, Optional, Sequence, TextIO - import sys +from typing import Callable, Optional, Sequence, TextIO, Union + from unitary.examples.quantum_rpg import qaracter _USER_INPUT = Callable[[str], str] @@ -56,9 +56,9 @@ def get_user_input_number( def get_multiple_user_inputs( get_user_input: _USER_INPUT, - *prompts: Sequence[Callable[[], int] | Callable[[], str]], + *prompts: Sequence[Union[Callable[[], int], Callable[[], str]]], file: TextIO = sys.stdout, -) -> Sequence[int | str]: +) -> Sequence[Union[int, str]]: """Runs multiple number or string prompts and returns their results. After all inputs have been provided the last prompt asks for confirmation if diff --git a/unitary/examples/quantum_rpg/input_helpers_test.py b/unitary/examples/quantum_rpg/input_helpers_test.py index 21a12fa6..86339245 100644 --- a/unitary/examples/quantum_rpg/input_helpers_test.py +++ b/unitary/examples/quantum_rpg/input_helpers_test.py @@ -39,8 +39,7 @@ def test_get_user_input_number_invalid(): def test_get_user_input_number_max(): - get_input = input_helpers.get_user_input_function( - ["0", "-1", "a", "7", "3"]) + get_input = input_helpers.get_user_input_function(["0", "-1", "a", "7", "3"]) output = io.StringIO() assert ( input_helpers.get_user_input_number(get_input, file=output, max_number=4) == 3 diff --git a/unitary/examples/quantum_rpg/main_loop_test.py b/unitary/examples/quantum_rpg/main_loop_test.py index 321eb6a2..efa6b978 100644 --- a/unitary/examples/quantum_rpg/main_loop_test.py +++ b/unitary/examples/quantum_rpg/main_loop_test.py @@ -11,10 +11,10 @@ # 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. -from typing import cast - import copy import io +from typing import cast + import unitary.alpha as alpha import unitary.examples.quantum_rpg.ascii_art as ascii_art import unitary.examples.quantum_rpg.classes as classes @@ -328,7 +328,9 @@ def test_bad_load() -> None: def test_battle() -> None: c = classes.Analyst("Mensing") state = game_state.GameState( - party=[c], user_input=["e", "south", "m", "1", "1", "quit"], file=io.StringIO() + party=[c], + user_input=["e", "south", "m", "1", "1", "", "quit"], + file=io.StringIO(), ) loop = main_loop.MainLoop(state=state, world=world.World(example_world())) loop.loop() @@ -366,6 +368,8 @@ def test_battle() -> None: m) Measure enemy qubit. q) Read Quantopedia. ?) Help. +[enter]) Confirm selection. +r) Select again. ------------------------------------------------------------ Battle Summary @@ -385,7 +389,9 @@ def test_battle() -> None: def test_lost_battle() -> None: c = classes.Engineer("Mensing") state = game_state.GameState( - party=[c], user_input=["e", "south", "x", "1", "1", "quit"], file=io.StringIO() + party=[c], + user_input=["e", "south", "x", "1", "1", "", "quit"], + file=io.StringIO(), ) assert state.party[0].name == "Mensing" assert len(state.party[0].active_qubits()) == 1 @@ -427,6 +433,8 @@ def test_lost_battle() -> None: x) Attack with X gate. q) Read Quantopedia. ?) Help. +[enter]) Confirm selection. +r) Select again. Observer watcher measures Mensing_1 as HURT. ------------------------------------------------------------ Battle Summary @@ -450,7 +458,9 @@ def test_escaped_battle(): c = classes.Engineer("Mensing") c.add_quantum_effect(alpha.Flip(), 1) state = game_state.GameState( - party=[c], user_input=["e", "south", "x", "1", "1", "quit"], file=io.StringIO() + party=[c], + user_input=["e", "south", "x", "1", "1", "", "quit"], + file=io.StringIO(), ) assert state.party[0].name == "Mensing" assert len(state.party[0].active_qubits()) == 1 @@ -492,6 +502,8 @@ def test_escaped_battle(): x) Attack with X gate. q) Read Quantopedia. ?) Help. +[enter]) Confirm selection. +r) Select again. Observer watcher measures Mensing_1 as HEALTHY. ------------------------------------------------------------ Battle Summary From e68c2abeccda11e4c74501bf92bf185d84d73ea1 Mon Sep 17 00:00:00 2001 From: Peter Solodov Date: Tue, 5 Mar 2024 10:56:47 +0100 Subject: [PATCH 6/7] fixed formatting --- unitary/alpha/quantum_world.py | 6 +++--- unitary/engine_utils.py | 8 +++++--- unitary/examples/quantum_rpg/ascii_art.py | 1 - unitary/examples/quantum_rpg/classes.py | 4 +--- unitary/quantum_chess/quantum_board.py | 6 +++--- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/unitary/alpha/quantum_world.py b/unitary/alpha/quantum_world.py index 28b291e4..daa00dff 100644 --- a/unitary/alpha/quantum_world.py +++ b/unitary/alpha/quantum_world.py @@ -111,9 +111,9 @@ def copy(self) -> "QuantumWorld": for remap in self.qubit_remapping_dict: new_dict = {} for key_obj, value_obj in remap.items(): - new_dict[ - new_world.get_object_by_name(key_obj.name) - ] = new_world.get_object_by_name(value_obj.name) + new_dict[new_world.get_object_by_name(key_obj.name)] = ( + new_world.get_object_by_name(value_obj.name) + ) new_world.qubit_remapping_dict.append(new_dict) new_world.qubit_remapping_dict_length = self.qubit_remapping_dict_length.copy() return new_world diff --git a/unitary/engine_utils.py b/unitary/engine_utils.py index 0f1c6bc9..5b78ee07 100644 --- a/unitary/engine_utils.py +++ b/unitary/engine_utils.py @@ -60,9 +60,11 @@ def _get_program_id(program: Any): return str(uuid.uuid4()) parts = [ - p - if len(p) <= chars_per_part - else p[: chars_per_part // 2] + p[-chars_per_part // 2 :] + ( + p + if len(p) <= chars_per_part + else p[: chars_per_part // 2] + p[-chars_per_part // 2 :] + ) for p in parts ] return "_".join(parts) diff --git a/unitary/examples/quantum_rpg/ascii_art.py b/unitary/examples/quantum_rpg/ascii_art.py index b6ed4d39..08eef985 100644 --- a/unitary/examples/quantum_rpg/ascii_art.py +++ b/unitary/examples/quantum_rpg/ascii_art.py @@ -1,6 +1,5 @@ """ASCII art and other large text constants.""" - # ASCII art generated with font # DOOM by Frans P. de Vries 18 Jun 1996 # based on Big by Glenn Chappell 4/93 -- based on Standard diff --git a/unitary/examples/quantum_rpg/classes.py b/unitary/examples/quantum_rpg/classes.py index 13473725..c22e2da5 100644 --- a/unitary/examples/quantum_rpg/classes.py +++ b/unitary/examples/quantum_rpg/classes.py @@ -75,9 +75,7 @@ def actions(self) -> Dict[str, Callable]: ), } if self.level >= 3: - action_dict[ - "s" - ] = ( + action_dict["s"] = ( lambda monster, qubit: f"Sample result {monster.sample(monster.quantum_object_name(qubit), False)}" ) return action_dict diff --git a/unitary/quantum_chess/quantum_board.py b/unitary/quantum_chess/quantum_board.py index 6ac79e03..4039e4c0 100644 --- a/unitary/quantum_chess/quantum_board.py +++ b/unitary/quantum_chess/quantum_board.py @@ -427,9 +427,9 @@ def _generate_accumulations(self, repetitions: int = 1000) -> None: probs = self._apply_cache( previous_probability, last_move, self.cache[cache_key] ) - self.move_history_probabilities_cache[ - -1 - ] = self._make_probability_history(repetitions, probs) + self.move_history_probabilities_cache[-1] = ( + self._make_probability_history(repetitions, probs) + ) # Remove entry from cached since it has been consumed. del self.cache[cache_key] return From c6a5503093a0695b8f8de1f8e22f0d7847fc1519 Mon Sep 17 00:00:00 2001 From: Peter Solodov Date: Tue, 5 Mar 2024 11:01:25 +0100 Subject: [PATCH 7/7] undo .gitignore change --- .gitignore | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitignore b/.gitignore index b8d0da42..00b93bc6 100644 --- a/.gitignore +++ b/.gitignore @@ -42,5 +42,3 @@ docs/generated # Notebook formatting script. nbformat - -build \ No newline at end of file