<img id="qweb" src="https://github.com/qentinelqi/qweb/raw/master/images/qweb.png" alt="QWeb">
> Keyword based test automation for the web.
---
![License][license-badge]
![Python versions][python-versions-badge]
![Release][pypi-badge]
![Windows Acceptance][win_ci_badge]
![Linux Acceptance][linux_ci_badge]
![MacOS Acceptance][macos_ci_badge]
[![Tested with][pace-badge]][pace-url]
[![Slack][slack-badge]][slack-url]
### Table of Contents
- [Introduction](#introduction)
- [Requirements](#requirements)
- [Installation](#installation)
- [Windows](#windows)
- [Linux/Mac](#linuxmac)
- [Automatic browser \& driver management](#automatic-browser--driver-management)
- [Manual driver management](#manual-driver-management)
- [Usage](#usage)
- [Keyword documentation](#keyword-documentation)
- [Examples](#examples)
- [Basic usage](#basic-usage)
- [Shadow DOMs and visibility](#shadow-doms-and-visibility)
- [Timeouts and anchors](#timeouts-and-anchors)
- [Other locators](#other-locators)
- [Working with tables](#working-with-tables)
- [Changing configuration](#changing-configuration)
- [Running with Python](#running-with-python)
- [Changelog](#changelog)
- [Contribute](#contribute)
- [Community](#community)
- [License](#license)
- [Resources](#resources)
---
## Introduction
QWeb is a powerful and versatile [Robot Framework](https://robotframework.org/) library that enables efficient and reliable web testing and automation. One of the key strengths of QWeb is its intuitive and user-friendly syntax, which makes it easy to write and maintain complex test cases.
QWeb aims to make web automation easy and maintainable by:
* providing an intuitive and **user-friendly syntax for writing and maintaining** complex test cases.
* providing **smart locators**: finding elements by text or by any attribute value with a simple syntax
* automatically handling latencies etc. via **automatic wait times**
* automatically handling **frames**
* automatically handling unexpected **alerts**
* providing support for finding **shadow dom** elements with an easy syntax
* providing **in-built bitmap comparison** for special cases where element can't be identified by any other means
* being **technology agnostic** and providing extensive support for various web technologies/frameworks
See [examples](#examples).
[Back To The Top](#qweb)
---
## Requirements
Python **3.9-3.12** and Robot Framework 5.0.1 or above.
(Note that support on Macs with Apple based silicon (M1) requires MacOS version 12/Monterey or above or [custom installation](https://github.com/qentinelqi/qweb/blob/master/docs/qweb_mac_m1_installation.md).)
## Installation
### Windows
```bash
pip install QWeb
```
### Linux/Mac
```bash
python3 -m pip install -U pip
python3 -m pip install QWeb
```
Running the above command installs also supported Selenium and Robot Framework versions + other dependencies.
### Automatic browser & driver management
Since Selenium 4.10.0 `browser drivers` can be automatically downloaded and installed using Selenium Manager, provided that driver is not found in PATH.
For Chrome `browser_version` can also be given; if your locally installed Chrome matches this version,
it will be used. If not, a suitable version of `Chrome for Testing` will be automatically downloaded.
Examples in [OpenBrowser keyword documentation](https://qentinelqi.github.io/qweb/QWeb.html#Open%20Browser)
### Manual driver management
For manual installation of drivers, please refer to [Selenium documentation](https://www.selenium.dev/selenium/docs/api/py/index.html#drivers) for more information OR use 3rd party packages like [WebDriverManager](https://pypi.org/project/webdrivermanager/).
[Back To The Top](#qweb)
---
## Usage
### Keyword documentation
See list of keywords and their usage on
* [Keyword documentation](https://qentinelqi.github.io/qweb/QWeb.html)
* [Copado Robotic Testing support pages](https://docs.copado.com/articles/#!copado-robotic-testing-publication/all-qwords)
[Back To The Top](#qweb)
### Examples
#### Basic usage
The preferred way to interact with web elements is using their **text** property. Most elements like input fields and dropdowns can also be found by closest label (text).
```RobotFramework
*** Settings ***
Library QWeb # Import library
*** Test Cases ***
Basic interaction
OpenBrowser https://qentinelqi.github.io/shop chrome # Open chrome and goto given url
VerifyText The animal friendly clothing company # Assert heading text
ClickText Scar the Lion # Click link text
ClickText Add to cart # Click *button* with specific text
DropDown Size Large # Select value (Large) from dropdown (Size)
```
#### Shadow DOMs and visibility
Most common cases when text or element is not found are:
- Element has (incorrectly?) some attribute set so, that it's considered invisible.
- Element is under shadow dom (i.e. has #shadow-root parent element)
QWeb searches for visible elements by default, but can be instructed to work with invisible elements as well. See keyword documentation of **SetConfig** and the following parameters:
- Visibility
- Offsetcheck
- InViewport
Elements under shadow DOM can not be found using xpaths. However, all *Text, *Item and *Input keywords do support extending the search to Shadow DOM elements. We intentionally keep this under separate setting for ensuring compatibility with older test cases.
Example:
```RobotFramework
*** Settings ***
Library QWeb # Import library
*** Test Cases ***
Click shadow dom element
SetConfig ShadowDOM True # extends search to shadow dom elements
OpenBrowser chrome://settings/content/popups chrome
ClickText Sites can send pop-ups
```
#### Timeouts and anchors
By default QWeb tries to locate the element 10 seconds (default time can be configured). Timeout can also be individually given for each keyword as an argument.
When text to be found is not unique, an 'anchor' argument can be given to pinpoint which instance of text we want to interact with. Anchor can be either another text nearby or index.
```RobotFramework
ClickText Sign-in
ClickText Sign-in timeout=30
ClickText Sign-in anchor=Email
ClickText Sign-in index=3
```
#### Other locators
Non-textual locators can be used with `ClickElement`and `ClickItem`keywords.
```RobotFramework
ClickElement xpath\=//button[@class="my_class"] # xpath
ClickItem Increment quantity # alt text
```
#### Working with tables
QWeb includes keywords to interact with table data easily.
Consider the following table as an example:
<img src="https://github.com/qentinelqi/qweb/raw/master/images/example_table.png" alt="Example table">
```RobotFramework
UseTable Firstname
${row}= GetTableRow //last # returns 5
${row}= GetTableRow //last skip_header=True # returns 4
...
${row}= GetTableRow Jim # returns 4
${row}= GetTableRow Jim skip_header=True # returns 3
${cell_value}= GetCellText r1c2 # Returns "John", first name is column 2.
${cell_value}= GetCellText r-1/c2 # Returns "Tina", -1 points to last row
${cell_value}= GetCellText r-2/c2 # Returns "Jim", -2 points to second last row
```
#### Changing configuration
QWeb's behavior can be changed with SetConfig keyword.
```RobotFramework
SetConfig SearchMode Draw # Highlight all found elements with blue rectangle
SetConfig DefaultTimeout 60s # change default/automatic timeout for all keywords
VerifyText User account created # Re-tries to find text "User account created" 60 seconds and then fails, if text is not visible
```
#### Running with Python
QWeb can be used directly with Python as well.
```Python
from QWeb import QWeb
qweb = QWeb()
qweb.open_browser("about:blank", "chrome")
qweb.go_to("https://www.w3schools.com/tags/tryit.asp?filename=tryhtml_select")
title = qweb.get_title()
# returns 'W3Schools Tryit Editor'
qweb.verify_text("The select element")
qweb.drop_down("Choose a car", "Saab")
qweb.click_text("Submit")
qweb.verify_text("Your input was received as:")
qweb.verify_text("cars=saab")
```
More examples on [QWeb tutorial](https://github.com/qentinelqi/qweb_workshop).
[Back To The Top](#qweb)
---
## Changelog
See [RELEASE.md](https://github.com/qentinelqi/qweb/blob/master/RELEASE.md)
[Back To The Top](#qweb)
## Contribute
Found an bug? Want to propose a new feature or improve documentation? Please start by checking our [contribution guide](https://github.com/qentinelqi/qweb/blob/master/CONTRIBUTING.md)
[Back To The Top](#qweb)
## Community
Want to join the community at Slack? On the official Robot Framework workspace, there is a QWeb channel where you can discuss with others about keywords, issues and improvements. [Join Now](https://robotframework.slack.com/archives/C029L0N3N81)
[Back To The Top](#qweb)
## License
Apache 2.0 License. See [LICENSE](https://github.com/qentinelqi/qweb/blob/master/LICENSE).
[Back To The Top](#qweb)
## Resources
* [QWeb home page](https://qentinel.com/qweb-open-source/)
* [QWeb tutorial](https://github.com/qentinelqi/qweb_workshop)
---
[license-badge]: https://img.shields.io/github/license/qentinelqi/qweb
[linux_ci_badge]: https://github.com/qentinelqi/qweb/actions/workflows/linux_acceptance.yml/badge.svg
[win_ci_badge]: https://github.com/qentinelqi/qweb/actions/workflows/win_acceptance.yml/badge.svg
[macos_ci_badge]: https://github.com/qentinelqi/qweb/actions/workflows/mac_acceptance.yml/badge.svg
[pace-url]: https://robotic.copado.com
[pace-badge]: https://img.shields.io/badge/Tested%20with-Copado%20Robotic%20Testing-blue
[python-versions-badge]: https://img.shields.io/pypi/pyversions/QWeb
[pypi-badge]: https://img.shields.io/pypi/v/QWeb?color=green
[slack-badge]: https://img.shields.io/badge/Slack-QWeb-blue?style=flat-square&logo=Slack
[slack-url]: https://robotframework.slack.com/archives/C029L0N3N81
Raw data
{
"_id": null,
"home_page": "https://github.com/qentinelqi/qweb/",
"name": "QWeb",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>3.7",
"maintainer_email": null,
"keywords": "test automation robot framework",
"author": "Copado Inc.",
"author_email": "copadorobotictesting@copado.com",
"download_url": "https://files.pythonhosted.org/packages/0f/42/f841606345ea7a5b585572a090328bcf3887cc2dda5fcc6b6e1e432dbc64/qweb-3.4.3.tar.gz",
"platform": null,
"description": "<img id=\"qweb\" src=\"https://github.com/qentinelqi/qweb/raw/master/images/qweb.png\" alt=\"QWeb\">\r\n\r\n> Keyword based test automation for the web.\r\n\r\n---\r\n![License][license-badge]\r\n![Python versions][python-versions-badge]\r\n![Release][pypi-badge]\r\n![Windows Acceptance][win_ci_badge]\r\n![Linux Acceptance][linux_ci_badge]\r\n![MacOS Acceptance][macos_ci_badge]\r\n[![Tested with][pace-badge]][pace-url]\r\n[![Slack][slack-badge]][slack-url]\r\n\r\n### Table of Contents\r\n\r\n- [Introduction](#introduction)\r\n- [Requirements](#requirements)\r\n- [Installation](#installation)\r\n - [Windows](#windows)\r\n - [Linux/Mac](#linuxmac)\r\n - [Automatic browser \\& driver management](#automatic-browser--driver-management)\r\n - [Manual driver management](#manual-driver-management)\r\n- [Usage](#usage)\r\n - [Keyword documentation](#keyword-documentation)\r\n - [Examples](#examples)\r\n - [Basic usage](#basic-usage)\r\n - [Shadow DOMs and visibility](#shadow-doms-and-visibility)\r\n - [Timeouts and anchors](#timeouts-and-anchors)\r\n - [Other locators](#other-locators)\r\n - [Working with tables](#working-with-tables)\r\n - [Changing configuration](#changing-configuration)\r\n - [Running with Python](#running-with-python)\r\n- [Changelog](#changelog)\r\n- [Contribute](#contribute)\r\n- [Community](#community)\r\n- [License](#license)\r\n- [Resources](#resources)\r\n\r\n---\r\n\r\n## Introduction\r\n\r\nQWeb is a powerful and versatile [Robot Framework](https://robotframework.org/) library that enables efficient and reliable web testing and automation. One of the key strengths of QWeb is its intuitive and user-friendly syntax, which makes it easy to write and maintain complex test cases. \r\n\r\nQWeb aims to make web automation easy and maintainable by:\r\n* providing an intuitive and **user-friendly syntax for writing and maintaining** complex test cases.\r\n* providing **smart locators**: finding elements by text or by any attribute value with a simple syntax\r\n* automatically handling latencies etc. via **automatic wait times**\r\n* automatically handling **frames**\r\n* automatically handling unexpected **alerts**\r\n* providing support for finding **shadow dom** elements with an easy syntax\r\n* providing **in-built bitmap comparison** for special cases where element can't be identified by any other means\r\n* being **technology agnostic** and providing extensive support for various web technologies/frameworks \r\n\r\nSee [examples](#examples).\r\n\r\n[Back To The Top](#qweb)\r\n\r\n---\r\n## Requirements\r\nPython **3.9-3.12** and Robot Framework 5.0.1 or above.\r\n\r\n(Note that support on Macs with Apple based silicon (M1) requires MacOS version 12/Monterey or above or [custom installation](https://github.com/qentinelqi/qweb/blob/master/docs/qweb_mac_m1_installation.md).)\r\n\r\n## Installation\r\n\r\n### Windows\r\n```bash\r\n pip install QWeb\r\n```\r\n\r\n### Linux/Mac\r\n```bash\r\n python3 -m pip install -U pip\r\n python3 -m pip install QWeb\r\n```\r\n\r\nRunning the above command installs also supported Selenium and Robot Framework versions + other dependencies.\r\n\r\n### Automatic browser & driver management\r\nSince Selenium 4.10.0 `browser drivers` can be automatically downloaded and installed using Selenium Manager, provided that driver is not found in PATH.\r\n\r\nFor Chrome `browser_version` can also be given; if your locally installed Chrome matches this version,\r\nit will be used. If not, a suitable version of `Chrome for Testing` will be automatically downloaded.\r\n\r\nExamples in [OpenBrowser keyword documentation](https://qentinelqi.github.io/qweb/QWeb.html#Open%20Browser)\r\n\r\n\r\n### Manual driver management\r\nFor manual installation of drivers, please refer to [Selenium documentation](https://www.selenium.dev/selenium/docs/api/py/index.html#drivers) for more information OR use 3rd party packages like [WebDriverManager](https://pypi.org/project/webdrivermanager/).\r\n\r\n\r\n[Back To The Top](#qweb)\r\n\r\n---\r\n\r\n\r\n\r\n## Usage\r\n\r\n### Keyword documentation\r\nSee list of keywords and their usage on \r\n\r\n* [Keyword documentation](https://qentinelqi.github.io/qweb/QWeb.html)\r\n* [Copado Robotic Testing support pages](https://docs.copado.com/articles/#!copado-robotic-testing-publication/all-qwords) \r\n\r\n[Back To The Top](#qweb)\r\n\r\n### Examples\r\n\r\n#### Basic usage\r\n\r\nThe preferred way to interact with web elements is using their **text** property. Most elements like input fields and dropdowns can also be found by closest label (text).\r\n\r\n```RobotFramework\r\n*** Settings ***\r\nLibrary QWeb # Import library\r\n\r\n*** Test Cases ***\r\nBasic interaction\r\n OpenBrowser https://qentinelqi.github.io/shop chrome # Open chrome and goto given url\r\n VerifyText The animal friendly clothing company # Assert heading text\r\n ClickText Scar the Lion # Click link text\r\n ClickText Add to cart # Click *button* with specific text\r\n DropDown Size Large # Select value (Large) from dropdown (Size)\r\n\r\n```\r\n#### Shadow DOMs and visibility\r\nMost common cases when text or element is not found are:\r\n- Element has (incorrectly?) some attribute set so, that it's considered invisible.\r\n- Element is under shadow dom (i.e. has #shadow-root parent element)\r\n\r\nQWeb searches for visible elements by default, but can be instructed to work with invisible elements as well. See keyword documentation of **SetConfig** and the following parameters:\r\n- Visibility\r\n- Offsetcheck\r\n- InViewport\r\n\r\nElements under shadow DOM can not be found using xpaths. However, all *Text, *Item and *Input keywords do support extending the search to Shadow DOM elements. We intentionally keep this under separate setting for ensuring compatibility with older test cases. \r\n\r\nExample:\r\n```RobotFramework\r\n*** Settings ***\r\nLibrary QWeb # Import library\r\n\r\n*** Test Cases ***\r\nClick shadow dom element\r\n SetConfig ShadowDOM True # extends search to shadow dom elements\r\n OpenBrowser chrome://settings/content/popups chrome\r\n ClickText Sites can send pop-ups \r\n```\r\n\r\n#### Timeouts and anchors\r\n\r\nBy default QWeb tries to locate the element 10 seconds (default time can be configured). Timeout can also be individually given for each keyword as an argument.\r\n\r\nWhen text to be found is not unique, an 'anchor' argument can be given to pinpoint which instance of text we want to interact with. Anchor can be either another text nearby or index.\r\n\r\n```RobotFramework\r\nClickText Sign-in\r\nClickText Sign-in timeout=30\r\n\r\nClickText Sign-in anchor=Email\r\nClickText Sign-in index=3\r\n```\r\n\r\n#### Other locators\r\n\r\nNon-textual locators can be used with `ClickElement`and `ClickItem`keywords.\r\n\r\n```RobotFramework\r\nClickElement xpath\\=//button[@class=\"my_class\"] # xpath\r\nClickItem Increment quantity # alt text\r\n\r\n```\r\n\r\n#### Working with tables\r\n\r\nQWeb includes keywords to interact with table data easily.\r\n\r\nConsider the following table as an example:\r\n<img src=\"https://github.com/qentinelqi/qweb/raw/master/images/example_table.png\" alt=\"Example table\">\r\n\r\n```RobotFramework\r\nUseTable Firstname\r\n\r\n${row}= GetTableRow //last # returns 5\r\n${row}= GetTableRow //last skip_header=True # returns 4\r\n...\r\n${row}= GetTableRow Jim # returns 4\r\n${row}= GetTableRow Jim skip_header=True # returns 3\r\n\r\n${cell_value}= GetCellText r1c2 # Returns \"John\", first name is column 2.\r\n\r\n${cell_value}= GetCellText r-1/c2 # Returns \"Tina\", -1 points to last row\r\n${cell_value}= GetCellText r-2/c2 # Returns \"Jim\", -2 points to second last row\r\n```\r\n\r\n#### Changing configuration\r\nQWeb's behavior can be changed with SetConfig keyword.\r\n\r\n```RobotFramework\r\n\r\nSetConfig SearchMode Draw # Highlight all found elements with blue rectangle\r\n\r\nSetConfig DefaultTimeout 60s # change default/automatic timeout for all keywords\r\nVerifyText User account created # Re-tries to find text \"User account created\" 60 seconds and then fails, if text is not visible\r\n```\r\n\r\n#### Running with Python\r\nQWeb can be used directly with Python as well.\r\n\r\n```Python\r\n\r\nfrom QWeb import QWeb\r\n\r\nqweb = QWeb()\r\n\r\nqweb.open_browser(\"about:blank\", \"chrome\")\r\nqweb.go_to(\"https://www.w3schools.com/tags/tryit.asp?filename=tryhtml_select\")\r\ntitle = qweb.get_title()\r\n# returns 'W3Schools Tryit Editor'\r\nqweb.verify_text(\"The select element\")\r\nqweb.drop_down(\"Choose a car\", \"Saab\")\r\nqweb.click_text(\"Submit\")\r\nqweb.verify_text(\"Your input was received as:\")\r\nqweb.verify_text(\"cars=saab\")\r\n\r\n```\r\n\r\nMore examples on [QWeb tutorial](https://github.com/qentinelqi/qweb_workshop).\r\n\r\n[Back To The Top](#qweb)\r\n\r\n---\r\n\r\n## Changelog\r\n\r\nSee [RELEASE.md](https://github.com/qentinelqi/qweb/blob/master/RELEASE.md)\r\n\r\n[Back To The Top](#qweb)\r\n\r\n## Contribute\r\n\r\nFound an bug? Want to propose a new feature or improve documentation? Please start by checking our [contribution guide](https://github.com/qentinelqi/qweb/blob/master/CONTRIBUTING.md)\r\n\r\n[Back To The Top](#qweb)\r\n\r\n## Community\r\n\r\nWant to join the community at Slack? On the official Robot Framework workspace, there is a QWeb channel where you can discuss with others about keywords, issues and improvements. [Join Now](https://robotframework.slack.com/archives/C029L0N3N81)\r\n\r\n[Back To The Top](#qweb)\r\n\r\n## License\r\n\r\nApache 2.0 License. See [LICENSE](https://github.com/qentinelqi/qweb/blob/master/LICENSE).\r\n\r\n\r\n[Back To The Top](#qweb)\r\n\r\n## Resources\r\n* [QWeb home page](https://qentinel.com/qweb-open-source/)\r\n* [QWeb tutorial](https://github.com/qentinelqi/qweb_workshop)\r\n\r\n\r\n\r\n---\r\n[license-badge]: https://img.shields.io/github/license/qentinelqi/qweb\r\n[linux_ci_badge]: https://github.com/qentinelqi/qweb/actions/workflows/linux_acceptance.yml/badge.svg\r\n[win_ci_badge]: https://github.com/qentinelqi/qweb/actions/workflows/win_acceptance.yml/badge.svg\r\n[macos_ci_badge]: https://github.com/qentinelqi/qweb/actions/workflows/mac_acceptance.yml/badge.svg\r\n[pace-url]: https://robotic.copado.com\r\n[pace-badge]: https://img.shields.io/badge/Tested%20with-Copado%20Robotic%20Testing-blue\r\n[python-versions-badge]: https://img.shields.io/pypi/pyversions/QWeb\r\n[pypi-badge]: https://img.shields.io/pypi/v/QWeb?color=green\r\n[slack-badge]: https://img.shields.io/badge/Slack-QWeb-blue?style=flat-square&logo=Slack\r\n[slack-url]: https://robotframework.slack.com/archives/C029L0N3N81\r\n",
"bugtrack_url": null,
"license": "Apache License 2.0",
"summary": "Keyword driven automation for the web",
"version": "3.4.3",
"project_urls": {
"Homepage": "https://github.com/qentinelqi/qweb/"
},
"split_keywords": [
"test",
"automation",
"robot",
"framework"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "db90065908533b0b1dd1670cc0b75a5e4d467b61b5ea7ac4edd095d9edae162c",
"md5": "7492cc9a04e98256fc85ed4a3e9a4252",
"sha256": "e1c09dfecba0d382eef1501d39555743f9f8f2dba2d29bd4b78f3a94ad66ddaa"
},
"downloads": -1,
"filename": "QWeb-3.4.3-py3-none-any.whl",
"has_sig": false,
"md5_digest": "7492cc9a04e98256fc85ed4a3e9a4252",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>3.7",
"size": 204166,
"upload_time": "2024-12-04T07:43:45",
"upload_time_iso_8601": "2024-12-04T07:43:45.148432Z",
"url": "https://files.pythonhosted.org/packages/db/90/065908533b0b1dd1670cc0b75a5e4d467b61b5ea7ac4edd095d9edae162c/QWeb-3.4.3-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "0f42f841606345ea7a5b585572a090328bcf3887cc2dda5fcc6b6e1e432dbc64",
"md5": "6b007350f1fa6bba5513ff11721035aa",
"sha256": "3ee149497d14d2f21754c862e1db63860f48835ddb65757734c58592b5e2a37e"
},
"downloads": -1,
"filename": "qweb-3.4.3.tar.gz",
"has_sig": false,
"md5_digest": "6b007350f1fa6bba5513ff11721035aa",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>3.7",
"size": 170576,
"upload_time": "2024-12-04T07:43:46",
"upload_time_iso_8601": "2024-12-04T07:43:46.438496Z",
"url": "https://files.pythonhosted.org/packages/0f/42/f841606345ea7a5b585572a090328bcf3887cc2dda5fcc6b6e1e432dbc64/qweb-3.4.3.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-12-04 07:43:46",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "qentinelqi",
"github_project": "qweb",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [
{
"name": "PyScreeze",
"specs": [
[
"==",
"0.1.28"
]
]
},
{
"name": "PyAutoGUI",
"specs": [
[
">=",
"0.9.53"
]
]
},
{
"name": "Pillow",
"specs": [
[
"<",
"11"
],
[
">=",
"10.3.0"
]
]
},
{
"name": "robotframework",
"specs": [
[
"<",
"8"
],
[
">=",
"5.0.1"
]
]
},
{
"name": "robotframework-debuglibrary",
"specs": [
[
"==",
"2.5.0"
]
]
},
{
"name": "selenium",
"specs": [
[
">=",
"4.27.0"
],
[
"<",
"5"
]
]
},
{
"name": "ply",
"specs": []
},
{
"name": "pynput",
"specs": [
[
"==",
"1.7.7"
]
]
},
{
"name": "setuptools",
"specs": [
[
">=",
"70.0.0"
]
]
},
{
"name": "numpy",
"specs": [
[
">=",
"1.23.5"
],
[
"<",
"2"
]
]
},
{
"name": "opencv-python",
"specs": [
[
"==",
"4.8.1.78"
]
]
},
{
"name": "requests",
"specs": [
[
"==",
"2.32.2"
]
]
},
{
"name": "slate3k",
"specs": [
[
"==",
"0.5.3"
]
]
},
{
"name": "scipy",
"specs": [
[
">=",
"1.7.3"
]
]
},
{
"name": "scikit-image",
"specs": [
[
"==",
"0.21"
]
]
},
{
"name": "scikit-image",
"specs": [
[
"==",
"0.24"
]
]
},
{
"name": "pyobjc-core",
"specs": [
[
">=",
"9.2"
]
]
},
{
"name": "pyobjc",
"specs": [
[
">=",
"9.2"
]
]
}
],
"tox": true,
"lcname": "qweb"
}