{ "cells": [ { "cell_type": "markdown", "id": "12632903-eae1-41cc-866b-d96d3fbcbb4f", "metadata": {}, "source": [ "This notebook illustrates the use of pexpect. For the instructions to work in this notebook, pexpect needs to be installed, which can be done with `pip install pexpect`." ] }, { "cell_type": "markdown", "id": "633a360c-6c47-4d9b-93d8-cbeaf8dd103c", "metadata": {}, "source": [ "The notebook was developed on a WSL Ubuntu, as the spawn on Windows does not work." ] }, { "cell_type": "markdown", "id": "2dcb44b2-1ba9-406e-99a4-76f6c829b2b9", "metadata": {}, "source": [ "Furthermore, Julia and SageMath are expected to be installed as well." ] }, { "cell_type": "markdown", "id": "c33d194e-ac14-4eda-bf1b-48b094444238", "metadata": {}, "source": [ "# 1. Hello Julia!" ] }, { "cell_type": "markdown", "id": "a711dc65-b1c3-4181-9435-e329361fb6ca", "metadata": {}, "source": [ "Let us call the Julia shell from within Python code." ] }, { "cell_type": "markdown", "id": "cadf3eb8-e217-4dc0-966f-cefcbd97f783", "metadata": {}, "source": [ "If the script `pexpect_hello_julia.py` was downloaded into the current folder from the course web site, then the following code shell should execute properly." ] }, { "cell_type": "code", "execution_count": 8, "id": "8519299f-615d-47eb-91a5-2b7b846fba24", "metadata": { "tags": [] }, "outputs": [], "source": [ "# !python pexpect_hello_julia.py only for terminal use" ] }, { "cell_type": "markdown", "id": "d6263303-0f75-47c1-b22e-ec835053fb07", "metadata": {}, "source": [ "The code in the script `pexpect_hello_julia.py` contains the following lines of code:" ] }, { "cell_type": "code", "execution_count": 9, "id": "eb3fba72-5fda-4f48-bb0c-3cd067fb85ad", "metadata": { "tags": [] }, "outputs": [], "source": [ "import pexpect\n", "child = pexpect.spawn('julia')" ] }, { "cell_type": "code", "execution_count": 10, "id": "88af2c54-2b5a-4a6c-9cd4-6d3e5164864b", "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "0" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "child.expect('julia>')" ] }, { "cell_type": "code", "execution_count": 11, "id": "70a0f06e-c793-49da-85f9-a5a3c210d2cf", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " \u001b[1m\u001b[32m_\u001b[0m\n", " \u001b[1m\u001b[34m_\u001b[0m \u001b[0m_\u001b[0m \u001b[1m\u001b[31m_\u001b[1m\u001b[32m(_)\u001b[1m\u001b[35m_\u001b[0m | Documentation: https://docs.julialang.org\n", " \u001b[1m\u001b[34m(_)\u001b[0m | \u001b[1m\u001b[31m(_)\u001b[0m \u001b[1m\u001b[35m(_)\u001b[0m |\n", " \u001b[0m_ _ _| |_ __ _\u001b[0m | Type \"?\" for help, \"]?\" for Pkg help.\n", " \u001b[0m| | | | | | |/ _` |\u001b[0m |\n", " \u001b[0m| | |_| | | | (_| |\u001b[0m | Version 1.9.3 (2023-08-24)\n", " \u001b[0m_/ |\\__'_|_|_|\\__'_|\u001b[0m | Official https://julialang.org/ release\n", "\u001b[0m|__/\u001b[0m |\n", "\n", "\u001b[0K\u001b[32m\u001b[1m" ] } ], "source": [ "print(child.before.decode('UTF-8'), end='')" ] }, { "cell_type": "markdown", "id": "c3290480-85f3-4bac-8698-57f4176d2ff7", "metadata": {}, "source": [ "# 2. Checking the Version of SageMath" ] }, { "cell_type": "code", "execution_count": 12, "id": "97c3ae6d-f837-4775-aa43-90f80022bdee", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "version of SageMath : 9.5\n" ] } ], "source": [ "!python sage_version_test.py" ] }, { "cell_type": "markdown", "id": "fb7cdd88-dfef-4fd1-a3bc-b39240da71c6", "metadata": {}, "source": [ "The function executed by `sage_version_test.py` is below:" ] }, { "cell_type": "code", "execution_count": 13, "id": "24be1468-0388-4850-a34f-0bf143008654", "metadata": { "tags": [] }, "outputs": [], "source": [ "def sage_version():\n", " \"\"\"\n", " Returns a string containing sage version\n", " and release date or None if sage cannot\n", " be found at the execution path.\n", " \"\"\"\n", " try:\n", " child = pexpect.spawn('/usr/bin/env sage')\n", " except:\n", " return None\n", " child.expect('sage')\n", " first = child.before.decode()\n", " lines = first.split('version')\n", " return lines[1][1:4]" ] }, { "cell_type": "code", "execution_count": 14, "id": "98540c84-7a75-4b31-9f0d-9f596a05a2ff", "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "'9.5'" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sage_version()" ] }, { "cell_type": "markdown", "id": "c646f422-8474-428c-aba4-f97876627d0d", "metadata": { "tags": [] }, "source": [ "# 3. A Number Guessing Game" ] }, { "cell_type": "markdown", "id": "9b401d5c-b740-4c62-bc8e-db164e2dd416", "metadata": {}, "source": [ "The code in the Python script `game_oracle_number.py` is shown below:" ] }, { "cell_type": "code", "execution_count": 8, "id": "9667bc77-abfc-4e05-a8bf-9e58b0aee8b2", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "# L-16 MCS 507 Wed 26 Sep 2023 : game_oracle_number.py\n", "\n", "\"\"\"\n", "This python script generates a random secret natural in [0,9] and\n", "enters a dialogue with the user playing the game of guessing the secret.\n", "\n", "This script is launched as a child process in pexpect_guessing_game.py\n", "where the script that launches the child process guesses the number.\n", "\"\"\"\n", "\n", "from random import randint\n", "SECRET = randint(0, 9)\n", "print('Welcome to our number guessing game!')\n", "while True:\n", " GUESS = int(input('give a natural number in [0, 9] : '))\n", " if GUESS == SECRET:\n", " break\n", " if GUESS < SECRET:\n", " print('-> your guess is too low')\n", " else:\n", " print('-> your guess is too high')\n", "print('Congratulations! You found the secret.')\n" ] } ], "source": [ "with open('game_oracle_number.py') as f:\n", " for line in f.readlines():\n", " print(line[:-1])" ] }, { "cell_type": "markdown", "id": "befb59a5-997b-40fb-be9a-f72508324330", "metadata": {}, "source": [ "With `pexpect` we can have another program play the game, as defined in the script `pexpect_guessing_game.py`." ] }, { "cell_type": "code", "execution_count": 9, "id": "1f693b7d-7027-47e5-856c-c82378a2fe2e", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "# L-16 MCS 507 Wed 26 Sep 2023 : pexpect_guessing_game.py\n", "\n", "\"\"\"\n", "This script spawns the game_oracle_number.py and then simply\n", "sends all consecutive integers till the game ends.\n", "\"\"\"\n", "\n", "print('spawning the oracle ...\\n')\n", "import pexpect\n", "CHILD = pexpect.spawn('/usr/bin/env python game_oracle_number.py')\n", "for i in range(10):\n", " CHILD.expect(':')\n", " CHILD.sendline(str(i))\n", " CHILD.read(6)\n", " REPLY = CHILD.after.decode()\n", " print('reply of oracle', REPLY)\n", " if REPLY[-2:] == 'Co':\n", " print('We guessed the secret!')\n", " break\n", "CHILD.close()\n", "print('\\nBye, script ends.')\n" ] } ], "source": [ "with open('pexpect_guessing_game.py') as f:\n", " for line in f.readlines():\n", " print(line[:-1])" ] }, { "cell_type": "code", "execution_count": 10, "id": "a19c8de0-f26a-4934-a059-bd962c8e9af6", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "spawning the oracle ...\n", "\n", "reply of oracle 0\n", "->\n", "reply of oracle 1\n", "->\n", "reply of oracle 2\n", "->\n", "reply of oracle 3\n", "->\n", "reply of oracle 4\n", "->\n", "reply of oracle 5\n", "->\n", "reply of oracle 6\n", "Co\n", "We guessed the secret!\n", "\n", "Bye, script ends.\n" ] } ], "source": [ "!python pexpect_guessing_game.py" ] }, { "cell_type": "markdown", "id": "45560f02-a93f-4849-bb70-9cae33c73ebf", "metadata": {}, "source": [ "# 4. Testing the Factorial of 50" ] }, { "cell_type": "code", "execution_count": 15, "id": "49ae24da-8b58-402a-abae-12084f0b2cf2", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "version of sage : 9.5\n", "executing import sympy as sp\n", "executing N = sp.factorial(50)\n", "executing assert(len(str(N)) == 65)\n", "executing F = sp.factorint(N)\n", "executing assert(len(F.keys()) == 15)\n", "executing print('test passed')\n", ": \u001b[0;38;5;28;1massert\u001b[0m(\u001b[0;38;5;24mlen\u001b[0m(\u001b[0;38;5;24mstr\u001b[0m(N)) == \u001b[0;38;5;20;1m65\u001b[0m)\u001b[31D\u001b[0m\n", "\u001b[J\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h\u001b[?2004l\u001b[?2004h\u001b[?25l\u001b[0m\u001b[?7l\u001b[0m\u001b[J\u001b[0;38;5;21m\n", "test passed\n" ] } ], "source": [ "!python factorial50_sympy_test.py" ] }, { "cell_type": "code", "execution_count": null, "id": "08d2780b-f6ca-488e-bdea-0a534c13beb5", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.10" } }, "nbformat": 4, "nbformat_minor": 5 }