{"id":31853409,"url":"https://github.com/avocado-framework/aexpect","last_synced_at":"2025-10-12T13:27:45.706Z","repository":{"id":30875690,"uuid":"34433344","full_name":"avocado-framework/aexpect","owner":"avocado-framework","description":"Python library used to control interactive programs","archived":false,"fork":false,"pushed_at":"2025-09-01T07:55:44.000Z","size":441,"stargazers_count":9,"open_issues_count":9,"forks_count":33,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-09-01T10:00:33.973Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/avocado-framework.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2015-04-23T04:20:19.000Z","updated_at":"2025-09-01T07:55:48.000Z","dependencies_parsed_at":"2024-01-31T14:26:05.330Z","dependency_job_id":"4f515634-9c9a-4542-b5c9-d43ba9f0afa8","html_url":"https://github.com/avocado-framework/aexpect","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/avocado-framework/aexpect","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/avocado-framework%2Faexpect","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/avocado-framework%2Faexpect/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/avocado-framework%2Faexpect/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/avocado-framework%2Faexpect/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/avocado-framework","download_url":"https://codeload.github.com/avocado-framework/aexpect/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/avocado-framework%2Faexpect/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279011453,"owners_count":26084947,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-12T02:00:06.719Z","response_time":53,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-10-12T13:27:43.225Z","updated_at":"2025-10-12T13:27:45.699Z","avatar_url":"https://github.com/avocado-framework.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"Aexpect: Control your interactive applications\n==============================================\n\nThis project provides services similar to the `pexpect` python library,\nso to speak, spawn and control interactive applications, such as `ssh`,\n`sftp` and others although it can be useful for pure streams as well.\n\nIt's enhanced with multi-pattern matching, convenience features for\nnot-only-linux terminals as well as support for terminals that \"spit\"\nextra output from time to time (eg. kernel messages) over the output.\n\nThere are also extra classes to simplify executing parts of a program\non a different location (distributed programming) or writing controls\nexecuted on another host (metaprogramming).\n\nSimple usage\n------------\n\n.. code-block:: python\n\n    \u003e\u003e\u003e import aexpect\n    \u003e\u003e\u003e import time\n    \u003e\u003e\u003e dir(aexpect)\n    ['Expect', 'ExpectError', 'ExpectProcessTerminatedError', 'ExpectTimeoutError', 'ShellCmdError', 'ShellError', 'ShellProcessTerminatedError', 'ShellSession', 'ShellStatusError', 'ShellTimeoutError', 'Spawn', 'Tail', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'client', 'exceptions', 'kill_tail_threads', 'remote', 'rss_client', 'run_bg', 'run_fg', 'run_tail', 'shared', 'utils']\n    \u003e\u003e\u003e session = aexpect.ShellSession(\"bash\")\n    \u003e\u003e\u003e session.cmd(\"ls /tmp/b\")\n    '1  2\\n'\n    \u003e\u003e\u003e session.cmd(\"cat /tmp/b/1\")\n    'Hello\\n'\n    \u003e\u003e\u003e session.cmd(\"cat /tmp/b/2\")\n    'World\\n'\n    \u003e\u003e\u003e dir(session)\n    ['_ShellSession__RE_STATUS', '__class__', '__del__', '__delattr__', '__dict__', '__dir__', '__doc__', '__enter__', '__eq__', '__exit__', '__format__', '__ge__', '__getattribute__', '__getinitargs__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_add_close_hook', '_add_reader', '_aexpect_helper', '_close_aexpect_helper', '_close_reader_fds', '_get_fd', '_join_thread', '_read_nonblocking', '_start_thread', '_tail', 'a_id', 'auto_close', 'close', 'close_hooks', 'closed', 'cmd', 'cmd_output', 'cmd_output_safe', 'cmd_status', 'cmd_status_output', 'command', 'ctrlpipe_filename', 'echo', 'encoding', 'get_command_output', 'get_command_status', 'get_command_status_output', 'get_id', 'get_output', 'get_pid', 'get_status', 'get_stripped_output', 'inpipe_filename', 'is_alive', 'is_defunct', 'is_responsive', 'kill', 'linesep', 'lock_client_starting_filename', 'lock_server_running_filename', 'log_file', 'log_file_fd', 'match_patterns', 'match_patterns_multiline', 'output_filename', 'output_func', 'output_params', 'output_prefix', 'prompt', 'read_nonblocking', 'read_until_any_line_matches', 'read_until_last_line_matches', 'read_until_last_word_matches', 'read_until_output_matches', 'read_up_to_prompt', 'reader_fds', 'reader_filenames', 'readers', 'remove_command_echo', 'remove_last_nonempty_line', 'send', 'send_ctrl', 'sendcontrol', 'sendline', 'server_log_filename', 'set_linesep', 'set_log_file', 'set_output_func', 'set_output_params', 'set_output_prefix', 'set_prompt', 'set_status_test_command', 'set_termination_func', 'set_termination_params', 'shell_pid_filename', 'status_filename', 'status_test_command', 'tail_thread', 'termination_func', 'termination_params', 'thread_name']\n    \u003e\u003e\u003e session.sendline(\"for I in $(seq 10); do echo $I; sleep 1; done\")\n    \u003e\u003e\u003e session.read_nonblocking(0.1, 2)\n    \u003e\u003e\u003e time.sleep(10)\n    \u003e\u003e\u003e session.read_nonblocking(0.1, 2)\n    '2\\n3\\n4\\n5\\n6\\n7\\n8\\n9\\n10\\n[medic@fedora ~ \\x1b[1;31m\\x1b[0m]$ '\n    \u003e\u003e\u003e session.sendline(\"for I in $(seq 10); do echo $I; sleep 1; done\")\n    \u003e\u003e\u003e session.read_nonblocking(1.5, 2)\n    '1\\n2\\n3\\n4\\n'\n    \u003e\u003e\u003e session.sendline(\"for I in $(seq 10); do echo $I; sleep 1; done\")\n    \u003e\u003e\u003e session.read_until_output_matches(\"3\", timeout=10)\n    (0, '1\\n2\\n3\\n')\n    \u003e\u003e\u003e session.sendline(\"for I in $(seq 10); do echo $I; sleep 1; done\")\n    \u003e\u003e\u003e session.read_until_output_matches([\"5\", \"7\", \"2\", \"foo\"], timeout=10)\n    (2, '1\\n2\\n')\n    \u003e\u003e\u003e session.cmd_status(\"true\")\n    0\n    \u003e\u003e\u003e session.cmd_status(\"false\")\n    1\n    \u003e\u003e\u003e session.is_alive()\n    True\n    \u003e\u003e\u003e session.is_responsive()\n    True\n    \u003e\u003e\u003e session.sendline(\"exit\")\n    \u003e\u003e\u003e session.is_alive()\n    False\n    \u003e\u003e\u003e session.is_responsive()\n    False\n\nTo get more information use the python `help()` command on various objects,\nwe do keep our docstrings updated. To get details about all `aexpect.client`\nobjects simply run `python -c \"import aexpect; [print(f'\\n{name}\\n{len(name)\n* '='}', func.__doc__) for name, func in aexpect.__dict__.items() if\nhasattr(func, '__doc__')]\"`\n\nDebugging\n---------\n\nUsing this even for purely bash-like constructs is good as you can leverage\nthe python debugger to interactively walk your issues. Especially the\n`pydevd` project is great as you can debug code from multiple machines on\nin a single Eclipse to see concurency issues. Execution is as simple as\n`pip install pydevd` on all machines, adding\n`pydevd.settrace(eclipse_machine_ip, True, True)` directly into the code\nreplacing the `eclipse_machine_ip` with IP address of the machine where\nEclipse will be running (eg. 127.0.0.1 for localhost). The following `True`\nare to redirect stdout/stderr which is usually useful but sometimes might\nlead to issues. Then you need to start the python debugger inside Eclipse\nby entering debug view and starting the pydev server\n`pydev-\u003eStart debug server`. Now you are ready and simply execute your\napplication the way you are used to, once it reaches the `pydev.settrace`\nline it will dial to the Eclipse server and show up in your debug view,\nshowing the code you are debugging even though it's on a different machine,\nallowing you to single-step across multiple processes.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Favocado-framework%2Faexpect","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Favocado-framework%2Faexpect","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Favocado-framework%2Faexpect/lists"}