{"library":"pyats","title":"pyATS","description":"pyATS (Python Automation Test System) is an end-to-end test automation framework, primarily developed by Cisco, designed for network engineers. It provides a robust infrastructure for defining network topologies, running tests against network devices (multi-vendor compatible), and parsing device outputs into structured data using the integrated Genie library. The current version is 26.3, and it maintains an active release cadence with frequent updates to parsers and APIs. [1, 4, 15, 18]","language":"python","status":"active","last_verified":"Sun May 17","install":{"commands":["pip install 'pyats[full]'","pip install pyats[library]","pip install pyats.contrib"],"cli":{"name":"pyats","version":"Usage:"}},"imports":["from pyats import aetest","from pyats.topology import loader","from genie.testbed import load","from pyats.easypy import run","from unicon.core.errors import ConnectionError"],"auth":{"required":false,"env_vars":[]},"quickstart":{"code":"import os\nimport logging\nfrom pyats import aetest\nfrom genie.testbed import load\nfrom unicon.core.errors import ConnectionError\n\n# Set up basic logging\nlogging.basicConfig(level=logging.INFO)\nlogger = logging.getLogger(__name__)\n\n# Create a dummy testbed file (testbed.yaml) for demonstration\n# In a real scenario, this would describe your network devices.\n# For a live environment, set environment variables for credentials:\n# export PYATS_TESTBED_USERNAME='your_username'\n# export PYATS_TESTBED_PASSWORD='your_password'\n\n# Example content for testbed.yaml:\n# devices:\n#   CSR1:\n#     os: iosxe\n#     connections:\n#       cli:\n#         protocol: ssh\n#         ip: 10.1.1.1 # Replace with your device IP\n#     credentials:\n#       default:\n#         username: '%ENV{PYATS_TESTBED_USERNAME}'\n#         password: '%ENV{PYATS_TESTBED_PASSWORD}'\n\nclass MyFirstTest(aetest.Testcase):\n\n    @aetest.setup\n    def setup(self, testbed):\n        # Load the testbed from a YAML file\n        try:\n            self_testbed = load(os.path.join(os.path.dirname(__file__), 'testbed.yaml'))\n            self.parent.parameters.update(testbed=self_testbed)\n            logger.info(f\"Testbed loaded successfully: {list(self_testbed.devices.keys())}\")\n        except Exception as e:\n            self.failed(f\"Failed to load testbed: {e}\")\n\n    @aetest.test\n    def connect_and_execute(self, testbed):\n        if not hasattr(self.parent.parameters, 'testbed'):\n            self.skipped('Testbed not loaded in setup.')\n            return\n\n        for device_name, device in self.parent.parameters['testbed'].devices.items():\n            logger.info(f\"Attempting to connect to device: {device_name}\")\n            try:\n                device.connect(init_exec_params={'timeout': 60})\n                logger.info(f\"Successfully connected to {device_name}\")\n\n                # Example: Execute a 'show version' command\n                output = device.execute('show version')\n                logger.info(f\"Output from {device_name}:\\n{output[:200]}...\") # Print first 200 chars\n\n                # Example: Parse 'show ip interface brief'\n                parsed_output = device.parse('show ip interface brief')\n                logger.info(f\"Parsed output from {device_name} (first entry): {list(parsed_output.values())[0] if parsed_output else 'No interfaces found'}\")\n\n                self.passed(f\"Successfully connected, executed, and parsed on {device_name}\")\n\n            except ConnectionError as e:\n                self.failed(f\"Connection failed for {device_name}: {e}\")\n            except Exception as e:\n                self.failed(f\"An error occurred with {device_name}: {e}\")\n            finally:\n                if device.is_connected():\n                    device.disconnect()\n                    logger.info(f\"Disconnected from {device_name}\")\n\n\n    @aetest.cleanup\n    def cleanup(self):\n        logger.info(\"Testcase cleanup completed.\")\n\nif __name__ == '__main__':\n    import sys\n    # Create a dummy testbed.yaml for local execution if it doesn't exist\n    testbed_path = os.path.join(os.path.dirname(__file__), 'testbed.yaml')\n    if not os.path.exists(testbed_path):\n        with open(testbed_path, 'w') as f:\n            f.write(\"\"\"\n---\ndevices:\n  CSR1:\n    os: iosxe\n    connections:\n      cli:\n        protocol: ssh\n        ip: 10.1.1.1 # REPLACE WITH YOUR DEVICE IP OR A MOCK IP FOR TESTING\n    credentials:\n      default:\n        username: '%ENV{PYATS_TESTBED_USERNAME}'\n        password: '%ENV{PYATS_TESTBED_PASSWORD}'\n            \"\"\")\n        logger.warning(f\"Created a dummy '{testbed_path}'. Please replace 10.1.1.1 with a real device IP and set environment variables PYATS_TESTBED_USERNAME and PYATS_TESTBED_PASSWORD.\")\n\n    # Set dummy env vars if not present for local execution to avoid crashes\n    os.environ.setdefault('PYATS_TESTBED_USERNAME', 'admin')\n    os.environ.setdefault('PYATS_TESTBED_PASSWORD', 'password')\n\n    # Run the AETest\n    aetest.main(argv=sys.argv)\n","lang":"python","description":"This quickstart demonstrates a basic pyATS test script. It defines a testcase with setup, test, and cleanup sections. The setup loads a testbed file (e.g., `testbed.yaml`) which describes the network devices and their connection details, including credentials often sourced from environment variables. The test section connects to a device, executes a 'show version' command, and then uses Genie's `parse()` method to get structured data from 'show ip interface brief'. Ensure `testbed.yaml` is configured with valid device IPs and credentials are set as environment variables (e.g., `PYATS_TESTBED_USERNAME`, `PYATS_TESTBED_PASSWORD`). The script includes a dummy `testbed.yaml` creation for local execution. Run with `python your_script_name.py` or `pyats run job your_script_name.py`. [3, 8, 20, 25]","tag":null,"tag_description":null,"last_tested":null,"results":[]},"compatibility":{"tag":null,"tag_description":null,"last_tested":"2026-05-17","installed_version":"25.9","pypi_latest":"26.4","is_stale":true,"summary":{"python_range":"3.10–3.9","success_rate":80,"avg_install_s":28.3,"avg_import_s":3.19,"wheel_type":"sdist"},"results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"full","exit_code":0,"wheel_type":"sdist","failure_reason":null,"import_side_effects":"clean","install_time_s":0.1,"import_time_s":2.89,"mem_mb":41.1,"disk_size":"1.2G"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"pyats.contrib","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"broken","install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":"75.1M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"library","exit_code":0,"wheel_type":"sdist","failure_reason":null,"import_side_effects":"clean","install_time_s":0.1,"import_time_s":2.98,"mem_mb":41.1,"disk_size":"931.4M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"full","exit_code":0,"wheel_type":"sdist","failure_reason":null,"import_side_effects":"clean","install_time_s":57.3,"import_time_s":2.67,"mem_mb":41.1,"disk_size":"993M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"pyats.contrib","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"broken","install_time_s":2.8,"import_time_s":null,"mem_mb":null,"disk_size":"146M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"library","exit_code":0,"wheel_type":"sdist","failure_reason":null,"import_side_effects":"clean","install_time_s":45.7,"import_time_s":2.41,"mem_mb":41.1,"disk_size":"715M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"full","exit_code":1,"wheel_type":null,"failure_reason":"build_error","import_side_effects":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"pyats.contrib","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"broken","install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":"82.8M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"library","exit_code":1,"wheel_type":null,"failure_reason":"build_error","import_side_effects":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"full","exit_code":0,"wheel_type":"sdist","failure_reason":null,"import_side_effects":"clean","install_time_s":55.8,"import_time_s":3.46,"mem_mb":45.1,"disk_size":"1.1G"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"pyats.contrib","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"broken","install_time_s":2.8,"import_time_s":null,"mem_mb":null,"disk_size":"154M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"library","exit_code":0,"wheel_type":"sdist","failure_reason":null,"import_side_effects":"clean","install_time_s":43.4,"import_time_s":3.49,"mem_mb":45,"disk_size":"756M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"full","exit_code":1,"wheel_type":null,"failure_reason":"build_error","import_side_effects":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"pyats.contrib","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"broken","install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":"73.1M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"library","exit_code":1,"wheel_type":null,"failure_reason":"build_error","import_side_effects":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"full","exit_code":0,"wheel_type":"sdist","failure_reason":null,"import_side_effects":"clean","install_time_s":59.1,"import_time_s":3.84,"mem_mb":45,"disk_size":"1.1G"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"pyats.contrib","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"broken","install_time_s":2.6,"import_time_s":null,"mem_mb":null,"disk_size":"144M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"library","exit_code":0,"wheel_type":"sdist","failure_reason":null,"import_side_effects":"clean","install_time_s":42.1,"import_time_s":3.97,"mem_mb":44.9,"disk_size":"736M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"full","exit_code":1,"wheel_type":null,"failure_reason":"build_error","import_side_effects":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"pyats.contrib","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"broken","install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":"69.8M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"library","exit_code":1,"wheel_type":null,"failure_reason":"build_error","import_side_effects":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"full","exit_code":0,"wheel_type":"sdist","failure_reason":null,"import_side_effects":"clean","install_time_s":56.6,"import_time_s":3.74,"mem_mb":47.1,"disk_size":"1.1G"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"pyats.contrib","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"broken","install_time_s":2.5,"import_time_s":null,"mem_mb":null,"disk_size":"143M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"library","exit_code":0,"wheel_type":"sdist","failure_reason":null,"import_side_effects":"clean","install_time_s":41.4,"import_time_s":3.82,"mem_mb":47.1,"disk_size":"735M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"full","exit_code":0,"wheel_type":"sdist","failure_reason":null,"import_side_effects":"clean","install_time_s":0.1,"import_time_s":2.96,"mem_mb":36.9,"disk_size":"972.1M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"pyats.contrib","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"broken","install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":"74.0M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"library","exit_code":0,"wheel_type":"sdist","failure_reason":null,"import_side_effects":"clean","install_time_s":0.1,"import_time_s":2.93,"mem_mb":36.8,"disk_size":"691.1M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"full","exit_code":0,"wheel_type":"sdist","failure_reason":null,"import_side_effects":"clean","install_time_s":68.7,"import_time_s":2.67,"mem_mb":36.9,"disk_size":"1.3G"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"pyats.contrib","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"broken","install_time_s":3.1,"import_time_s":null,"mem_mb":null,"disk_size":"146M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"library","exit_code":0,"wheel_type":"sdist","failure_reason":null,"import_side_effects":"clean","install_time_s":53.7,"import_time_s":2.85,"mem_mb":36.8,"disk_size":"992M"}]}}