From 66c6ce8a02dcada1be8aad0479611e4a520e0f1b Mon Sep 17 00:00:00 2001 From: mshriver Date: Tue, 28 Jul 2026 08:37:15 -0500 Subject: [PATCH 1/3] Update pre-commit versions Co-authored-by: Claude --- .pre-commit-config.yaml | 10 +++++----- testing/conftest.py | 1 - testing/test_descriptionlist.py | 1 - testing/test_drawer.py | 1 - testing/test_radio.py | 1 - testing/test_title.py | 1 - 6 files changed, 5 insertions(+), 10 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0b28a883..e8901a06 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,20 +1,20 @@ repos: - repo: https://github.com/asottile/reorder-python-imports - rev: v3.10.0 + rev: v3.17.0 hooks: - id: reorder-python-imports language_version: python3 args: - --application-directories=.:src - repo: https://github.com/psf/black - rev: 23.7.0 + rev: 26.5.1 hooks: - id: black args: [--safe, --quiet, --line-length, "100"] language_version: python3 require_serial: true - repo: https://github.com/PyCQA/flake8 - rev: 6.0.0 + rev: 7.3.0 hooks: - id: flake8 language_version: python3 @@ -22,7 +22,7 @@ repos: - --max-line-length=100 - --ignore=W503,E203 - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v6.0.0 hooks: - id: trailing-whitespace language_version: python3 @@ -31,7 +31,7 @@ repos: - id: debug-statements language_version: python3 - repo: https://github.com/asottile/pyupgrade - rev: v3.9.0 + rev: v3.21.2 hooks: - id: pyupgrade language_version: python3 diff --git a/testing/conftest.py b/testing/conftest.py index 06de9efa..30e347ec 100644 --- a/testing/conftest.py +++ b/testing/conftest.py @@ -7,7 +7,6 @@ from wait_for import wait_for from widgetastic.browser import Browser - OPTIONS = {"firefox": webdriver.FirefoxOptions(), "chrome": webdriver.ChromeOptions()} diff --git a/testing/test_descriptionlist.py b/testing/test_descriptionlist.py index cb110bd8..7662a538 100644 --- a/testing/test_descriptionlist.py +++ b/testing/test_descriptionlist.py @@ -3,7 +3,6 @@ from widgetastic_patternfly4 import DescriptionList - TESTING_PAGE_URL = "https://patternfly-react-main.surge.sh/components/description-list" diff --git a/testing/test_drawer.py b/testing/test_drawer.py index b8d21df6..1e8f9df9 100644 --- a/testing/test_drawer.py +++ b/testing/test_drawer.py @@ -5,7 +5,6 @@ from widgetastic_patternfly4 import Drawer from widgetastic_patternfly4.button import Button - TESTING_PAGE_URL = "https://patternfly-react.surge.sh/components/drawer" diff --git a/testing/test_radio.py b/testing/test_radio.py index 30f61f1f..8be655c1 100644 --- a/testing/test_radio.py +++ b/testing/test_radio.py @@ -3,7 +3,6 @@ from widgetastic_patternfly4 import Radio - TESTING_PAGE_URL = "https://patternfly-react.surge.sh/components/radio" diff --git a/testing/test_title.py b/testing/test_title.py index 2eeaddde..0d817b0a 100644 --- a/testing/test_title.py +++ b/testing/test_title.py @@ -2,7 +2,6 @@ from widgetastic_patternfly4 import Title - TESTING_PAGE_URL = "https://patternfly-react.surge.sh/components/title" From 265e460def84c02ac6ef2a1325125c31e195e360 Mon Sep 17 00:00:00 2001 From: mshriver Date: Tue, 28 Jul 2026 08:44:42 -0500 Subject: [PATCH 2/3] Add hatch envs for tests Co-authored-by: Claude --- README.md | 42 ++++++++++++++++++++++++++++++++++++++++++ pyproject.toml | 21 +++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/README.md b/README.md index 33b3a808..36d23e66 100644 --- a/README.md +++ b/README.md @@ -109,3 +109,45 @@ of workers: ```bash BROWSER=firefox pytest -v testing -n 4 ``` + +### Running tests with Hatch + +Tests can also be run through [Hatch](https://hatch.pypa.io/) managed environments, which take care of +installing the `dev` extras (`pytest`, `pytest-cov`, `pytest-xdist`) in an isolated virtual environment. + +Run the test suite against the default environment (`BROWSER=firefox` by default): + +```bash +hatch run test +``` + +Run tests in parallel: + +```bash +hatch run test-parallel +``` + +Run tests with coverage: + +```bash +hatch run test-cov +``` + +Override the browser or pass extra pytest args: + +```bash +BROWSER=chrome hatch run test testing/test_button.py -v +``` + +A `test` matrix environment is also defined, covering the same Python (3.8-3.10) and browser +(chrome, firefox) combinations exercised in CI. Run a single combination: + +```bash +hatch run test.py3.10-chrome:test-cov +``` + +Or run the full matrix: + +```bash +hatch run test:test-cov +``` diff --git a/pyproject.toml b/pyproject.toml index ccdc5992..df6bbf8f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,3 +48,24 @@ strict-naming = false [tool.hatch.version] source = "vcs" + +[tool.hatch.envs.default] +features = ["dev"] + +[tool.hatch.envs.default.env-vars] +BROWSER = "firefox" + +[tool.hatch.envs.default.scripts] +test = "pytest {args:testing}" +test-parallel = "pytest -n auto {args:testing}" +test-cov = "pytest --no-cov-on-fail --cov=widgetastic_patternfly4 --cov-append {args:testing}" +cov-combine = "coverage combine" +cov-report = "coverage report" +cov-xml = "coverage xml" + +[[tool.hatch.envs.test.matrix]] +python = ["3.8", "3.9", "3.10"] +browser = ["chrome", "firefox"] + +[tool.hatch.envs.test.overrides] +matrix.browser.env-vars = "BROWSER" From 2562f7190acc1bf3b036e7d2d12c8044979cd657 Mon Sep 17 00:00:00 2001 From: mshriver Date: Tue, 28 Jul 2026 09:47:51 -0500 Subject: [PATCH 3/3] pre-commit application Co-authored-by: Claude --- .github/workflows/deploy.yml | 31 ++++--- .github/workflows/tests.yaml | 43 +++++----- .pre-commit-config.yaml | 33 ++------ README.md | 21 +++-- docs/conf.py | 4 +- pyproject.toml | 46 ++++++++-- src/widgetastic_patternfly4/__init__.py | 83 +++++++++---------- src/widgetastic_patternfly4/alert.py | 11 ++- src/widgetastic_patternfly4/bulletchart.py | 6 +- src/widgetastic_patternfly4/button.py | 15 ++-- src/widgetastic_patternfly4/card.py | 5 +- src/widgetastic_patternfly4/chipgroup.py | 8 +- src/widgetastic_patternfly4/clipboardcopy.py | 4 +- .../contextselector.py | 3 +- src/widgetastic_patternfly4/donutchart.py | 8 +- src/widgetastic_patternfly4/dropdown.py | 10 +-- .../duallistselector.py | 3 +- src/widgetastic_patternfly4/formselect.py | 12 +-- src/widgetastic_patternfly4/linechart.py | 5 +- src/widgetastic_patternfly4/menu.py | 14 +--- src/widgetastic_patternfly4/modal.py | 4 +- src/widgetastic_patternfly4/navigation.py | 6 +- src/widgetastic_patternfly4/ouia.py | 23 +++-- src/widgetastic_patternfly4/pagination.py | 11 +-- src/widgetastic_patternfly4/progress.py | 5 +- src/widgetastic_patternfly4/radio.py | 5 +- src/widgetastic_patternfly4/select.py | 18 ++-- src/widgetastic_patternfly4/switch.py | 4 +- src/widgetastic_patternfly4/table.py | 20 ++--- src/widgetastic_patternfly4/tabs.py | 5 +- src/widgetastic_patternfly4/title.py | 3 +- testing/conftest.py | 3 +- testing/ouia/test_contextselector_ouia.py | 4 +- testing/ouia/test_dropdown_ouia.py | 3 +- testing/ouia/test_modal_ouia.py | 6 +- testing/ouia/test_table_ouia.py | 2 +- testing/test_cardview.py | 8 +- testing/test_chipgroup.py | 8 +- testing/test_contextselector.py | 3 +- testing/test_drawer.py | 3 +- testing/test_dropdown.py | 15 ++-- testing/test_duallistselector.py | 3 +- testing/test_formselect.py | 10 ++- testing/test_menu.py | 3 +- testing/test_modal.py | 3 +- testing/test_nav.py | 3 +- testing/test_optionsmenu.py | 3 +- testing/test_pagination.py | 4 +- testing/test_select.py | 4 +- testing/test_slider.py | 6 +- testing/test_switch.py | 3 +- testing/test_table.py | 19 +++-- testing/test_tabs.py | 3 +- 53 files changed, 256 insertions(+), 332 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 5ffd82a7..6dba7b7f 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -7,25 +7,22 @@ on: jobs: deploy: - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 + environment: + name: pypi + url: https://pypi.org/p/widgetastic.patternfly4 + permissions: + id-token: write # For trusted publishing steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.13' - name: Install dependencies - run: pip install twine + run: pip install pip twine -U - name: Build a wheel run: pip wheel --no-deps -w dist . + - name: Test package + run: twine check dist/* - name: Deploy to PyPI - uses: pypa/gh-action-pypi-publish@v1.4.1 - with: - user: __token__ - password: ${{ secrets.PYPI_TOKEN }} - - name: Create a release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag_name: ${{ github.ref }} - release_name: Release ${{ github.ref }} - draft: false - prerelease: false + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index d59b1cc1..1c69d026 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -10,55 +10,50 @@ on: jobs: test: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: + fail-fast: false matrix: browser: [chrome, firefox] - python-version: ["3.8", "3.9", "3.10"] + python-version: ["3.10", "3.11", "3.12", "3.13"] steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - pip install -U pip wheel - pip install .[dev] + - name: Install Hatch + run: pip install -U pip hatch - name: Fetch selenium image run: podman pull selenium/standalone-${{ matrix.browser }}:4.9.0-20230421 - name: Test with pytest - env: - BROWSER: ${{ matrix.browser }} run: | - pytest -v -n 5 --no-cov-on-fail \ - --cov=widgetastic_patternfly4 \ - --cov-append + hatch run test.py${{ matrix.python-version }}-${{ matrix.browser }}:test-cov -v -n 5 mv .coverage ${{ strategy.job-index }}_coverage - name: Upload coverage artifact - uses: "actions/upload-artifact@v3" + uses: "actions/upload-artifact@v4" with: name: ${{ strategy.job-index }}_coverage path: ${{ strategy.job-index }}_coverage submit_coverage: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 needs: test steps: - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 with: - python-version: "3.8" - - uses: actions/checkout@v3 - - name: Install coverage - run: pip install coverage + python-version: "3.10" + - uses: actions/checkout@v4 + - name: Install Hatch + run: pip install -U pip hatch - name: Download coverage artifacts - uses: actions/download-artifact@v4.1.7 + uses: actions/download-artifact@v4 with: path: /tmp/coverage - name: Combine coverage data files run: | - coverage combine -a $(find /tmp/coverage -type f) - coverage xml -o /tmp/coverage.xml + hatch run coverage:combine -a $(find /tmp/coverage -type f) + hatch run coverage:xml -o /tmp/coverage.xml - name: Publish coverage - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v5 with: files: /tmp/coverage.xml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e8901a06..6f61ebbf 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,37 +1,14 @@ repos: - - repo: https://github.com/asottile/reorder-python-imports - rev: v3.17.0 + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.16.0 hooks: - - id: reorder-python-imports - language_version: python3 + - id: ruff args: - - --application-directories=.:src - - repo: https://github.com/psf/black - rev: 26.5.1 - hooks: - - id: black - args: [--safe, --quiet, --line-length, "100"] - language_version: python3 - require_serial: true - - repo: https://github.com/PyCQA/flake8 - rev: 7.3.0 - hooks: - - id: flake8 - language_version: python3 - args: - - --max-line-length=100 - - --ignore=W503,E203 + - '--fix' + - id: ruff-format - repo: https://github.com/pre-commit/pre-commit-hooks rev: v6.0.0 hooks: - id: trailing-whitespace - language_version: python3 - id: end-of-file-fixer - language_version: python3 - id: debug-statements - language_version: python3 - - repo: https://github.com/asottile/pyupgrade - rev: v3.21.2 - hooks: - - id: pyupgrade - language_version: python3 diff --git a/README.md b/README.md index 36d23e66..a364898c 100644 --- a/README.md +++ b/README.md @@ -127,23 +127,24 @@ Run tests in parallel: hatch run test-parallel ``` -Run tests with coverage: +Run tests with coverage (extra flags, e.g. `-n 5`, are appended after the `testing` target): ```bash -hatch run test-cov +BROWSER=chrome hatch run test-cov -v -n 5 ``` -Override the browser or pass extra pytest args: +Run a single test file: ```bash BROWSER=chrome hatch run test testing/test_button.py -v ``` -A `test` matrix environment is also defined, covering the same Python (3.8-3.10) and browser -(chrome, firefox) combinations exercised in CI. Run a single combination: +A `test` matrix environment is also defined, covering the same Python (3.10-3.13) and browser +(chrome, firefox) combinations exercised in CI - this is what `.github/workflows/tests.yaml` uses. +Run a single combination: ```bash -hatch run test.py3.10-chrome:test-cov +hatch run test.py3.10-chrome:test-cov -v -n 5 ``` Or run the full matrix: @@ -151,3 +152,11 @@ Or run the full matrix: ```bash hatch run test:test-cov ``` + +Coverage data from multiple runs can be combined/reported using the detached `coverage` environment +(also used by the `submit_coverage` CI job): + +```bash +hatch run coverage:combine +hatch run coverage:xml +``` diff --git a/docs/conf.py b/docs/conf.py index fec4fe3f..52eb1772 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -11,6 +11,8 @@ import os import sys +from sphinx.ext.apidoc import main as apidoc_main + modules_path = os.path.abspath("../src/widgetastic_patternfly4") sys.path.insert(0, modules_path) @@ -53,8 +55,6 @@ def run_apidoc(_): - from sphinx.ext.apidoc import main as apidoc_main - cur_dir = os.path.abspath(".") output_path = os.path.join(cur_dir, "source") apidoc_main(["-e", "-f", "-o", output_path, modules_path, "--force"]) diff --git a/pyproject.toml b/pyproject.toml index df6bbf8f..226c38da 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,9 +2,10 @@ classifiers = [ "Programming Language :: Python", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Software Development :: Quality Assurance", "Topic :: Software Development :: Testing", @@ -16,13 +17,14 @@ license = {file = "LICENSE"} maintainers = [ {name = "Nikhil Dhandre", email = "ndhandre@redhat.com"}, {name = "Egor Shamardin", email = "eshamard@redhat.com"}, + {name = "Mike Shriver", email = "mshriver@redhat.com"}, ] name = "widgetastic.patternfly4" readme = "README.md" -requires-python = ">=3.8" +requires-python = ">=3.10" dependencies = [ - "widgetastic.core>=1.0.0", + "widgetastic.core>=1.0.0,<2.0.0", ] [project.optional-dependencies] @@ -32,6 +34,7 @@ dev = [ "pytest-cov", "pytest-xdist", "codecov", + "selenium", ] doc = ["sphinx"] @@ -58,14 +61,39 @@ BROWSER = "firefox" [tool.hatch.envs.default.scripts] test = "pytest {args:testing}" test-parallel = "pytest -n auto {args:testing}" -test-cov = "pytest --no-cov-on-fail --cov=widgetastic_patternfly4 --cov-append {args:testing}" -cov-combine = "coverage combine" -cov-report = "coverage report" -cov-xml = "coverage xml" +test-cov = "pytest --no-cov-on-fail --cov=widgetastic_patternfly4 --cov-append testing {args}" [[tool.hatch.envs.test.matrix]] -python = ["3.8", "3.9", "3.10"] +python = ["3.10", "3.11", "3.12", "3.13"] browser = ["chrome", "firefox"] [tool.hatch.envs.test.overrides] matrix.browser.env-vars = "BROWSER" + +[tool.hatch.envs.coverage] +detached = true +dependencies = ["coverage[toml]"] + +[tool.hatch.envs.coverage.scripts] +combine = "coverage combine {args}" +report = "coverage report {args}" +xml = "coverage xml {args}" + +[tool.hatch.envs.lint] +dependencies = ["pre-commit"] + +[tool.hatch.envs.lint.scripts] +check = "pre-commit run --all-files" + +[tool.pytest.ini_options] +testpaths = ["testing"] + +[tool.ruff] +line-length = 100 + +[tool.ruff.lint] +select = ["F", "I", "PL", "UP"] +# PLR0913/PLR0917: widgetastic widgets conventionally take several positional +# constructor args (parent, locator, ...); PLW1641: pre-existing __eq__-without- +# __hash__ classes kept as-is to avoid changing equality/hashing semantics. +extend-ignore = ["PLR2004", "PLE0643", "PLR0913", "PLR0917", "PLW1641"] diff --git a/src/widgetastic_patternfly4/__init__.py b/src/widgetastic_patternfly4/__init__.py index 42538544..8f162523 100644 --- a/src/widgetastic_patternfly4/__init__.py +++ b/src/widgetastic_patternfly4/__init__.py @@ -3,63 +3,56 @@ from .bulletchart import BulletChart from .button import Button from .calendarmonth import CalendarMonth -from .card import Card -from .card import CardCheckBox -from .card import CardForCardGroup -from .card import CardGroup -from .chipgroup import CategoryChipGroup -from .chipgroup import Chip -from .chipgroup import ChipGroup -from .chipgroup import ChipGroupToolbar -from .chipgroup import ChipGroupToolbarCategory -from .chipgroup import ChipReadOnlyError -from .chipgroup import StandAloneChipGroup +from .card import Card, CardCheckBox, CardForCardGroup, CardGroup +from .chipgroup import ( + CategoryChipGroup, + Chip, + ChipGroup, + ChipGroupToolbar, + ChipGroupToolbarCategory, + ChipReadOnlyError, + StandAloneChipGroup, +) from .clipboardcopy import ClipboardCopy from .contextselector import ContextSelector from .descriptionlist import DescriptionList from .donutchart import DonutChart from .drawer import Drawer -from .dropdown import Dropdown -from .dropdown import DropdownDisabled -from .dropdown import DropdownItemDisabled -from .dropdown import DropdownItemNotFound -from .dropdown import GroupDropdown -from .dropdown import SplitButtonDropdown -from .duallistselector import DualListSelector -from .duallistselector import SearchDualListSelector -from .formselect import FormSelect -from .formselect import FormSelectDisabled -from .formselect import FormSelectOptionDisabled -from .formselect import FormSelectOptionNotFound +from .dropdown import ( + Dropdown, + DropdownDisabled, + DropdownItemDisabled, + DropdownItemNotFound, + GroupDropdown, + SplitButtonDropdown, +) +from .duallistselector import DualListSelector, SearchDualListSelector +from .formselect import ( + FormSelect, + FormSelectDisabled, + FormSelectOptionDisabled, + FormSelectOptionNotFound, +) from .linechart import LineChart -from .menu import CheckboxMenu -from .menu import Menu -from .menu import MenuItemDisabled -from .menu import MenuItemNotFound +from .menu import CheckboxMenu, Menu, MenuItemDisabled, MenuItemNotFound from .modal import Modal -from .navigation import Navigation -from .navigation import NavSelectionNotFound +from .navigation import Navigation, NavSelectionNotFound from .optionsmenu import OptionsMenu -from .pagination import CompactPagination -from .pagination import Pagination -from .pagination import PaginationNavDisabled +from .pagination import CompactPagination, Pagination, PaginationNavDisabled from .piechart import PieChart from .popover import Popover from .progress import Progress from .radio import Radio -from .select import CheckboxSelect -from .select import Select -from .select import SelectItemDisabled -from .select import SelectItemNotFound -from .slider import InputSlider -from .slider import Slider -from .switch import Switch -from .switch import SwitchDisabled -from .table import ColumnNotExpandable -from .table import CompoundExpandableTable -from .table import ExpandableTable -from .table import PatternflyTable -from .table import RowNotExpandable +from .select import CheckboxSelect, Select, SelectItemDisabled, SelectItemNotFound +from .slider import InputSlider, Slider +from .switch import Switch, SwitchDisabled +from .table import ( + ColumnNotExpandable, + CompoundExpandableTable, + ExpandableTable, + PatternflyTable, + RowNotExpandable, +) from .tabs import Tab from .title import Title diff --git a/src/widgetastic_patternfly4/alert.py b/src/widgetastic_patternfly4/alert.py index ef278c04..65b70ba8 100644 --- a/src/widgetastic_patternfly4/alert.py +++ b/src/widgetastic_patternfly4/alert.py @@ -57,12 +57,11 @@ def type(self): for class_ in self.browser.classes(self): if class_ in self.TYPE_MAPPING: return self.TYPE_MAPPING[class_] - else: - raise ValueError( - "Could not find a proper alert type." - f"\nAvailable classes: {self.TYPE_MAPPING!r} " - f"\nAlert has: {self.browser.classes(self)!r}" - ) + raise ValueError( + "Could not find a proper alert type." + f"\nAvailable classes: {self.TYPE_MAPPING!r} " + f"\nAlert has: {self.browser.classes(self)!r}" + ) def assert_no_error(self): """Asserts that the warning is not of the error type.""" diff --git a/src/widgetastic_patternfly4/bulletchart.py b/src/widgetastic_patternfly4/bulletchart.py index b987794b..5538910e 100644 --- a/src/widgetastic_patternfly4/bulletchart.py +++ b/src/widgetastic_patternfly4/bulletchart.py @@ -1,9 +1,7 @@ import re from widgetastic.utils import ParametrizedLocator -from widgetastic.widget import ParametrizedView -from widgetastic.widget import Text -from widgetastic.widget import View +from widgetastic.widget import ParametrizedView, Text, View from widgetastic.xpath import quote @@ -128,7 +126,7 @@ class BulletChart(View): def __init__(self, parent=None, id=None, locator=None, logger=None, *args, **kwargs): View.__init__(self, parent=parent, logger=logger) if id: - self.locator = ".//div[@id={}]".format(quote(id)) + self.locator = f".//div[@id={quote(id)}]" elif locator: self.locator = locator else: diff --git a/src/widgetastic_patternfly4/button.py b/src/widgetastic_patternfly4/button.py index 8626b26c..f7c03ef9 100644 --- a/src/widgetastic_patternfly4/button.py +++ b/src/widgetastic_patternfly4/button.py @@ -1,6 +1,5 @@ from widgetastic.utils import ParametrizedLocator -from widgetastic.widget import ClickableMixin -from widgetastic.widget import Widget +from widgetastic.widget import ClickableMixin, Widget from widgetastic.xpath import quote @@ -36,7 +35,7 @@ def disabled(self): return check1 or check2 or self.browser.get_attribute("disabled", self) is not None def __repr__(self): - return "{}{}".format(type(self).__name__, self.locator) + return f"{type(self).__name__}{self.locator}" @property def title(self): @@ -69,25 +68,25 @@ def _generate_locator(self, *text, **kwargs): if kwargs: # classes should have been the only kwarg combined with text args raise TypeError("If you pass button text then only pass classes in addition") if len(text) == 1: - locator_conditions = "normalize-space(.)={}".format(quote(text[0])) + locator_conditions = f"normalize-space(.)={quote(text[0])}" elif len(text) == 2 and text[0].lower() == "contains": - locator_conditions = "contains(normalize-space(.), {})".format(quote(text[1])) + locator_conditions = f"contains(normalize-space(.), {quote(text[1])})" else: raise TypeError("An illegal combination of args/kwargs") else: # Join the kwargs, if any locator_conditions = " and ".join( - "@{}={}".format(attr, quote(value)) for attr, value in kwargs.items() + f"@{attr}={quote(value)}" for attr, value in kwargs.items() ) if classes: if locator_conditions: locator_conditions += " and " locator_conditions += " and ".join( - "contains(@class, {})".format(quote(klass)) for klass in classes + f"contains(@class, {quote(klass)})" for klass in classes ) if locator_conditions: - locator_conditions = "and ({})".format(locator_conditions) + locator_conditions = f"and ({locator_conditions})" return ( ".//*[(self::a or self::button or (self::input and " diff --git a/src/widgetastic_patternfly4/card.py b/src/widgetastic_patternfly4/card.py index 9520a9bf..85671dd9 100644 --- a/src/widgetastic_patternfly4/card.py +++ b/src/widgetastic_patternfly4/card.py @@ -1,8 +1,5 @@ from widgetastic.utils import ParametrizedLocator -from widgetastic.widget import Checkbox -from widgetastic.widget import GenericLocatorWidget -from widgetastic.widget import ParametrizedView -from widgetastic.widget import View +from widgetastic.widget import Checkbox, GenericLocatorWidget, ParametrizedView, View class BaseCard: diff --git a/src/widgetastic_patternfly4/chipgroup.py b/src/widgetastic_patternfly4/chipgroup.py index 3fbeabb4..1e41b173 100644 --- a/src/widgetastic_patternfly4/chipgroup.py +++ b/src/widgetastic_patternfly4/chipgroup.py @@ -1,8 +1,5 @@ from wait_for import wait_for -from widgetastic.widget import ParametrizedLocator -from widgetastic.widget import ParametrizedView -from widgetastic.widget import Text -from widgetastic.widget import View +from widgetastic.widget import ParametrizedLocator, ParametrizedView, Text, View from .button import Button @@ -322,8 +319,7 @@ class ChipGroupToolbar(View): # The parent of the chip group toolbar can be any element type # The locator should be the parent node which holds all the pf-c-chip-group elements TOOLBAR_LOCATOR = ( - ".//ul[contains(@class, 'pf-c-chip-group') and " - "contains(@class, 'pf-m-toolbar')]/parent::*" + ".//ul[contains(@class, 'pf-c-chip-group') and contains(@class, 'pf-m-toolbar')]/parent::*" ) overflow = OldOverflowChip( diff --git a/src/widgetastic_patternfly4/clipboardcopy.py b/src/widgetastic_patternfly4/clipboardcopy.py index 325450f3..72bcdfc2 100644 --- a/src/widgetastic_patternfly4/clipboardcopy.py +++ b/src/widgetastic_patternfly4/clipboardcopy.py @@ -1,7 +1,5 @@ from widgetastic.utils import ParametrizedLocator -from widgetastic.widget import GenericLocatorWidget -from widgetastic.widget import Text -from widgetastic.widget import TextInput +from widgetastic.widget import GenericLocatorWidget, Text, TextInput from widgetastic_patternfly4.button import Button diff --git a/src/widgetastic_patternfly4/contextselector.py b/src/widgetastic_patternfly4/contextselector.py index e641a804..3ff511d8 100644 --- a/src/widgetastic_patternfly4/contextselector.py +++ b/src/widgetastic_patternfly4/contextselector.py @@ -4,8 +4,7 @@ class BaseContextSelector: ITEMS_LOCATOR = ".//ul[@class='pf-c-context-selector__menu-list']/li" ITEM_LOCATOR = ( - ".//*[contains(@class, 'pf-c-context-selector__menu-list-item')" - " and normalize-space(.)={}]" + ".//*[contains(@class, 'pf-c-context-selector__menu-list-item') and normalize-space(.)={}]" ) SEARCH_INPUT_LOCATOR = ".//input[@type='search']" SEARCH_BUTTON_LOCATOR = ".//button[contains(@id, 'pf-context-selector-search-button')]" diff --git a/src/widgetastic_patternfly4/donutchart.py b/src/widgetastic_patternfly4/donutchart.py index 9a9c7734..9de37c92 100644 --- a/src/widgetastic_patternfly4/donutchart.py +++ b/src/widgetastic_patternfly4/donutchart.py @@ -1,17 +1,13 @@ import re -from widgetastic.widget import ClickableMixin -from widgetastic.widget import ParametrizedLocator -from widgetastic.widget import ParametrizedView -from widgetastic.widget import View -from widgetastic.widget import Widget +from widgetastic.widget import ClickableMixin, ParametrizedLocator, ParametrizedView, View, Widget from widgetastic.xpath import quote class DonutLegendItem(ParametrizedView, ClickableMixin): PARAMETERS = ("label_text",) ROOT = ParametrizedLocator( - ".//*[name()='text']" "/*[name()='tspan' and contains(., '{label_text}')]" + ".//*[name()='text']/*[name()='tspan' and contains(., '{label_text}')]" ) ALL_ITEMS = ".//*[name()='text']/*[name()='tspan']" LEGEND_ITEM_REGEX = re.compile(r"(.*?): ([\d]+)") diff --git a/src/widgetastic_patternfly4/dropdown.py b/src/widgetastic_patternfly4/dropdown.py index e3875c5a..b5842bdb 100644 --- a/src/widgetastic_patternfly4/dropdown.py +++ b/src/widgetastic_patternfly4/dropdown.py @@ -1,11 +1,9 @@ from contextlib import contextmanager from wait_for import wait_for_decorator -from widgetastic.exceptions import NoSuchElementException -from widgetastic.exceptions import UnexpectedAlertPresentException +from widgetastic.exceptions import NoSuchElementException, UnexpectedAlertPresentException from widgetastic.utils import ParametrizedLocator -from widgetastic.widget import Checkbox -from widgetastic.widget import Widget +from widgetastic.widget import Checkbox, Widget from widgetastic.xpath import quote @@ -124,7 +122,7 @@ def item_element(self, item, close=True, **kwargs): items_string = "These items are present: {}".format("; ".join(items)) else: items_string = "The dropdown is probably not present" - raise DropdownItemNotFound("Item {!r} not found. {}".format(item, items_string)) + raise DropdownItemNotFound(f"Item {item!r} not found. {items_string}") def item_enabled(self, item, close=True, **kwargs): """Returns whether the given item is enabled. @@ -233,7 +231,7 @@ def item_element(self, item, group_name=None, close=True): ) except NoSuchElementException: raise DropdownItemNotFound( - 'Following group "{}" not found. Available are: {}'.format(group_name, self.groups) + f'Following group "{group_name}" not found. Available are: {self.groups}' ) return super().item_element(item, close=close, **kwargs) diff --git a/src/widgetastic_patternfly4/duallistselector.py b/src/widgetastic_patternfly4/duallistselector.py index d01c6db7..f372611f 100644 --- a/src/widgetastic_patternfly4/duallistselector.py +++ b/src/widgetastic_patternfly4/duallistselector.py @@ -1,5 +1,4 @@ -from widgetastic.widget import GenericLocatorWidget -from widgetastic.widget import TextInput +from widgetastic.widget import GenericLocatorWidget, TextInput from .button import Button diff --git a/src/widgetastic_patternfly4/formselect.py b/src/widgetastic_patternfly4/formselect.py index 44f9239c..db8c853b 100644 --- a/src/widgetastic_patternfly4/formselect.py +++ b/src/widgetastic_patternfly4/formselect.py @@ -81,18 +81,14 @@ def fill(self, value): FormSelectOptionNotFound: if option not found """ if not self.is_enabled: - raise FormSelectDisabled("{} is not enabled".format(repr(self))) + raise FormSelectDisabled(f"{repr(self)} is not enabled") if value not in self.all_options: raise FormSelectOptionNotFound( - 'Option "{}" not found in {}. Available options: {}'.format( - value, repr(self), self.all_options - ) + f'Option "{value}" not found in {repr(self)}. Available options: {self.all_options}' ) elif value not in self.all_enabled_options: raise FormSelectOptionDisabled( - 'Option "{}" is disabled in {}. Enabled options are: {}'.format( - value, repr(self), self.all_enabled_options - ) + f'Option "{value}" is disabled in {repr(self)}. Enabled options are: {self.all_enabled_options}' ) self._select_element.select_by_visible_text(value) @@ -101,7 +97,7 @@ def read(self): return self.browser.text(self._select_element.first_selected_option) def __repr__(self): - return "{}({!r})".format(type(self).__name__, self.locator) + return f"{type(self).__name__}({self.locator!r})" class FormSelect(BaseFormSelect, GenericLocatorWidget): diff --git a/src/widgetastic_patternfly4/linechart.py b/src/widgetastic_patternfly4/linechart.py index 8ff20504..6c0d7f79 100644 --- a/src/widgetastic_patternfly4/linechart.py +++ b/src/widgetastic_patternfly4/linechart.py @@ -1,5 +1,4 @@ -from widgetastic.widget import ParametrizedLocator -from widgetastic.widget import View +from widgetastic.widget import ParametrizedLocator, View from widgetastic.xpath import quote from widgetastic_patternfly4.bulletchart import Legend @@ -37,7 +36,7 @@ def __init__(self, parent=None, id=None, locator=None, logger=None): assert id or locator, "Provide id or locator." if id: - self.locator = ".//div[@id={}]".format(quote(id)) + self.locator = f".//div[@id={quote(id)}]" else: self.locator = locator diff --git a/src/widgetastic_patternfly4/menu.py b/src/widgetastic_patternfly4/menu.py index 424eea77..590a75cb 100644 --- a/src/widgetastic_patternfly4/menu.py +++ b/src/widgetastic_patternfly4/menu.py @@ -1,8 +1,6 @@ from widgetastic.exceptions import NoSuchElementException -from .dropdown import Dropdown -from .dropdown import DropdownItemDisabled -from .dropdown import DropdownItemNotFound +from .dropdown import Dropdown, DropdownItemDisabled, DropdownItemNotFound class MenuItemDisabled(DropdownItemDisabled): @@ -95,9 +93,7 @@ def item_element(self, item, close=True): return super().item_element(item, close) except DropdownItemNotFound: raise MenuItemNotFound( - "Item {!r} not found in {}. Available items: {}".format( - item, repr(self), self.items - ) + f"Item {item!r} not found in {repr(self)}. Available items: {self.items}" ) def item_select(self, item): @@ -113,10 +109,8 @@ def item_select(self, item): return super().item_select(item) except DropdownItemDisabled: raise MenuItemDisabled( - 'Item "{}" of {} is disabled\n' - "The following items are available and enabled: {}".format( - item, repr(self), self.enabled_items - ) + f'Item "{item}" of {repr(self)} is disabled\n' + f"The following items are available and enabled: {self.enabled_items}" ) def fill(self, value): diff --git a/src/widgetastic_patternfly4/modal.py b/src/widgetastic_patternfly4/modal.py index 41af7df9..b0cfbdde 100644 --- a/src/widgetastic_patternfly4/modal.py +++ b/src/widgetastic_patternfly4/modal.py @@ -16,9 +16,7 @@ class BaseModal: BODY = ".//div[contains(@class, 'pf-c-modal-box__body')]" FOOTER = ".//*[contains(@class, 'pf-c-modal-box__footer')]/child::node()" - FOOTER_ITEM = ( - ".//*[contains(@class, 'pf-c-modal-box__footer')]" "/button[normalize-space(.)={}]" - ) + FOOTER_ITEM = ".//*[contains(@class, 'pf-c-modal-box__footer')]/button[normalize-space(.)={}]" TITLE = ".//h1[contains(@class, 'pf-c-title') or contains(@class, 'pf-c-modal-box__title')]" CLOSE = ".//button[@aria-label='Close']" diff --git a/src/widgetastic_patternfly4/navigation.py b/src/widgetastic_patternfly4/navigation.py index 14129d8c..2ca42ecd 100644 --- a/src/widgetastic_patternfly4/navigation.py +++ b/src/widgetastic_patternfly4/navigation.py @@ -126,7 +126,7 @@ def select(self, *levels, **kwargs): current_item = self.browser.element(self.SUB_ITEMS_ROOT, parent=li) def __repr__(self): - return "{}({!r})".format(type(self).__name__, self.ROOT) + return f"{type(self).__name__}({self.ROOT!r})" class Navigation(BaseNavigation, Widget): @@ -138,11 +138,11 @@ def __init__(self, parent, label=None, id=None, locator=None, logger=None): quoted_label = quote(label) if label else "" if label: - label_part = " and @label={} or @aria-label={}".format(quoted_label, quoted_label) + label_part = f" and @label={quoted_label} or @aria-label={quoted_label}" else: label_part = "" - id_part = " and @id={}".format(quote(id)) if id else "" + id_part = f" and @id={quote(id)}" if id else "" if locator is not None: self.locator = locator elif label_part or id_part: diff --git a/src/widgetastic_patternfly4/ouia.py b/src/widgetastic_patternfly4/ouia.py index 3a64b8fb..160cd75d 100644 --- a/src/widgetastic_patternfly4/ouia.py +++ b/src/widgetastic_patternfly4/ouia.py @@ -1,5 +1,4 @@ -from widgetastic.ouia import OUIAGenericView -from widgetastic.ouia import OUIAGenericWidget +from widgetastic.ouia import OUIAGenericView, OUIAGenericWidget from widgetastic.ouia.input import TextInput as BaseOuiaTextInput from widgetastic.ouia.text import Text as BaseOuiaText from widgetastic.widget.table import Table @@ -11,22 +10,20 @@ from widgetastic_patternfly4.card import BaseCard from widgetastic_patternfly4.clipboardcopy import BaseClipboardCopy from widgetastic_patternfly4.contextselector import BaseContextSelector -from widgetastic_patternfly4.dropdown import BaseDropdown -from widgetastic_patternfly4.dropdown import BaseGroupDropdown -from widgetastic_patternfly4.dropdown import BaseSplitButtonDropdown +from widgetastic_patternfly4.dropdown import ( + BaseDropdown, + BaseGroupDropdown, + BaseSplitButtonDropdown, +) from widgetastic_patternfly4.formselect import BaseFormSelect -from widgetastic_patternfly4.menu import BaseCheckboxMenu -from widgetastic_patternfly4.menu import BaseMenu +from widgetastic_patternfly4.menu import BaseCheckboxMenu, BaseMenu from widgetastic_patternfly4.modal import BaseModal from widgetastic_patternfly4.navigation import BaseNavigation from widgetastic_patternfly4.optionsmenu import BaseOptionsMenu -from widgetastic_patternfly4.pagination import BaseCompactPagination -from widgetastic_patternfly4.pagination import BasePagination -from widgetastic_patternfly4.select import BaseCheckboxSelect -from widgetastic_patternfly4.select import BaseSelect +from widgetastic_patternfly4.pagination import BaseCompactPagination, BasePagination +from widgetastic_patternfly4.select import BaseCheckboxSelect, BaseSelect from widgetastic_patternfly4.switch import BaseSwitch -from widgetastic_patternfly4.table import BaseExpandableTable -from widgetastic_patternfly4.table import BasePatternflyTable +from widgetastic_patternfly4.table import BaseExpandableTable, BasePatternflyTable from widgetastic_patternfly4.title import BaseTitle diff --git a/src/widgetastic_patternfly4/pagination.py b/src/widgetastic_patternfly4/pagination.py index f70503fb..7bf3e24e 100644 --- a/src/widgetastic_patternfly4/pagination.py +++ b/src/widgetastic_patternfly4/pagination.py @@ -3,10 +3,7 @@ from selenium.webdriver.common.keys import Keys from widgetastic.utils import ParametrizedLocator -from widgetastic.widget import GenericLocatorWidget -from widgetastic.widget import Text -from widgetastic.widget import TextInput -from widgetastic.widget import View +from widgetastic.widget import GenericLocatorWidget, Text, TextInput, View from .optionsmenu import OptionsMenu @@ -164,16 +161,14 @@ def cache_per_page_value(self): def set_per_page(self, count): """Sets the number of items per page. (Will cast to str)""" value = str(count) - value_per_page = "{} per page".format(value) + value_per_page = f"{value} per page" items = self._options.items if value_per_page in items: self._options.item_select(value_per_page) elif value in items: self._options.item_select(value) else: - raise ValueError( - "count '{}' is not a valid option in the pagination dropdown".format(count) - ) + raise ValueError(f"count '{count}' is not a valid option in the pagination dropdown") def go_to_page(self, value): """Navigate to custom page number.""" diff --git a/src/widgetastic_patternfly4/progress.py b/src/widgetastic_patternfly4/progress.py index 1ae2d3b9..30fd5a83 100644 --- a/src/widgetastic_patternfly4/progress.py +++ b/src/widgetastic_patternfly4/progress.py @@ -32,9 +32,8 @@ def status(self): for class_ in self.browser.classes(self): if class_ in self.STATUS_TYPE_MAPPING: return self.STATUS_TYPE_MAPPING[class_] - else: - default_alert_type = "info" - return default_alert_type + default_alert_type = "info" + return default_alert_type class Progress(BaseProgress, Widget): diff --git a/src/widgetastic_patternfly4/radio.py b/src/widgetastic_patternfly4/radio.py index 4e9c61c5..abe974e2 100644 --- a/src/widgetastic_patternfly4/radio.py +++ b/src/widgetastic_patternfly4/radio.py @@ -1,7 +1,4 @@ -from widgetastic.widget import Checkbox -from widgetastic.widget import ParametrizedLocator -from widgetastic.widget import Text -from widgetastic.widget import View +from widgetastic.widget import Checkbox, ParametrizedLocator, Text, View # https://patternfly-react.surge.sh/components/radio diff --git a/src/widgetastic_patternfly4/select.py b/src/widgetastic_patternfly4/select.py index f3dcf880..f9695052 100644 --- a/src/widgetastic_patternfly4/select.py +++ b/src/widgetastic_patternfly4/select.py @@ -1,8 +1,6 @@ from widgetastic.exceptions import NoSuchElementException -from .dropdown import Dropdown -from .dropdown import DropdownItemDisabled -from .dropdown import DropdownItemNotFound +from .dropdown import Dropdown, DropdownItemDisabled, DropdownItemNotFound class SelectItemDisabled(DropdownItemDisabled): @@ -37,9 +35,7 @@ def item_element(self, item, close=True): return super().item_element(item, close) except DropdownItemNotFound: raise SelectItemNotFound( - "Item {!r} not found in {}. Available items: {}".format( - item, repr(self), self.items - ) + f"Item {item!r} not found in {repr(self)}. Available items: {self.items}" ) def item_select(self, item): @@ -55,10 +51,8 @@ def item_select(self, item): return super().item_select(item) except DropdownItemDisabled: raise SelectItemDisabled( - 'Item "{}" of {} is disabled\n' - "The following items are available and enabled: {}".format( - item, repr(self), self.enabled_items - ) + f'Item "{item}" of {repr(self)} is disabled\n' + f"The following items are available and enabled: {self.enabled_items}" ) def fill(self, value): @@ -81,7 +75,9 @@ class BaseCheckboxSelect(BaseSelect): """ ITEMS_LOCATOR = ".//label[contains(@class, 'pf-c-select__menu-item')]" - ITEM_LOCATOR = f"{ITEMS_LOCATOR}/span[starts-with(normalize-space(.), {{}})]/preceding-sibling::input" # noqa + ITEM_LOCATOR = ( + f"{ITEMS_LOCATOR}/span[starts-with(normalize-space(.), {{}})]/preceding-sibling::input" # noqa + ) def item_select(self, items, close=True): """Opens the Checkbox and selects the desired item. diff --git a/src/widgetastic_patternfly4/switch.py b/src/widgetastic_patternfly4/switch.py index 250d910e..a537bab1 100644 --- a/src/widgetastic_patternfly4/switch.py +++ b/src/widgetastic_patternfly4/switch.py @@ -43,7 +43,7 @@ def is_enabled(self): def fill(self, value): """Fills a Switch with the supplied value.""" if not self.is_enabled: - raise SwitchDisabled("{} is disabled".format(repr(self))) + raise SwitchDisabled(f"{repr(self)} is disabled") if bool(value) == self.selected: return False else: @@ -55,7 +55,7 @@ def read(self): return self.selected def __repr__(self): - return "{}({!r})".format(type(self).__name__, self.locator) + return f"{type(self).__name__}({self.locator!r})" class Switch(BaseSwitch, GenericLocatorWidget): diff --git a/src/widgetastic_patternfly4/table.py b/src/widgetastic_patternfly4/table.py index 44c48217..04f0a307 100644 --- a/src/widgetastic_patternfly4/table.py +++ b/src/widgetastic_patternfly4/table.py @@ -1,10 +1,6 @@ from selenium.common.exceptions import NoSuchElementException from widgetastic.log import create_item_logger -from widgetastic.widget import Table -from widgetastic.widget import TableColumn -from widgetastic.widget import TableRow -from widgetastic.widget import Text -from widgetastic.widget import Widget +from widgetastic.widget import Table, TableColumn, TableRow, Text, Widget from widgetastic.widget.table import resolve_table_widget @@ -12,7 +8,7 @@ class HeaderColumn(TableColumn): """Represents a cell in the header row.""" def __locator__(self): - return "(./td|./th)[{}]".format(self.position + 1) + return f"(./td|./th)[{self.position + 1}]" @property def is_sortable(self): @@ -46,7 +42,7 @@ def __locator__(self): return "./thead/tr" def __repr__(self): - return "{}({!r})".format(type(self).__name__, self.parent) + return f"{type(self).__name__}({self.parent!r})" def __getitem__(self, item): if isinstance(item, str): @@ -149,7 +145,7 @@ class ExpandableTableHeaderColumn(TableColumn): def __locator__(self): """Override the locator to look inside the first 'tr' within the tbody""" - return "./tr[1]/th[{}]".format(self.position + 1) + return f"./tr[1]/th[{self.position + 1}]" class RowNotExpandable(Exception): @@ -157,7 +153,7 @@ def __init__(self, row): self.row = row def __str__(self): - return "Row is not expandable: {}".format(repr(self.row)) + return f"Row is not expandable: {repr(self.row)}" class ColumnNotExpandable(Exception): @@ -165,7 +161,7 @@ def __init__(self, column): self.column = column def __str__(self): - return "Column is not expandable: {}".format(repr(self.column)) + return f"Column is not expandable: {repr(self.column)}" class ExpandableTableRow(PatternflyTableRow): @@ -329,9 +325,9 @@ def __locator__(self): """Override the locator to look inside the first 'tr' within the tbody""" if self.position == 0: # we assume the th column is in the first position - return "./tr[1]/th[{}]".format(self.position + 1) + return f"./tr[1]/th[{self.position + 1}]" else: - return "./tr[1]/td[{}]".format(self.position) + return f"./tr[1]/td[{self.position}]" @property def is_expandable(self): diff --git a/src/widgetastic_patternfly4/tabs.py b/src/widgetastic_patternfly4/tabs.py index 76d385e6..c4ca0f89 100644 --- a/src/widgetastic_patternfly4/tabs.py +++ b/src/widgetastic_patternfly4/tabs.py @@ -17,8 +17,7 @@ class Tab(View): # Locator of the Tab selector TAB_LOCATOR = ParametrizedLocator( - './/div[contains(@class, "pf-c-tabs")]/ul' - "/li[button[normalize-space(.)={@tab_name|quote}]]" + './/div[contains(@class, "pf-c-tabs")]/ul/li[button[normalize-space(.)={@tab_name|quote}]]' ) ROOT = ParametrizedLocator( @@ -62,4 +61,4 @@ def child_widget_accessed(self, widget): self.select() def __repr__(self): - return "".format(self.tab_name) + return f"" diff --git a/src/widgetastic_patternfly4/title.py b/src/widgetastic_patternfly4/title.py index cbd0e372..91ec81b7 100644 --- a/src/widgetastic_patternfly4/title.py +++ b/src/widgetastic_patternfly4/title.py @@ -1,5 +1,4 @@ -from widgetastic.widget import ParametrizedLocator -from widgetastic.widget import Widget +from widgetastic.widget import ParametrizedLocator, Widget class BaseTitle: diff --git a/testing/conftest.py b/testing/conftest.py index 30e347ec..bce79c7a 100644 --- a/testing/conftest.py +++ b/testing/conftest.py @@ -48,12 +48,13 @@ def selenium_url(pytestconfig, browser_name, worker_id): f"selenium/standalone-{browser_name}:4.9.0-20230421", ], stdout=subprocess.PIPE, + check=False, ) print(f"VNC url: http://{host}:7900") yield f"http://{host}:4444" container_id = ps.stdout.decode("utf-8").strip() - subprocess.run(["podman", "kill", container_id], stdout=subprocess.DEVNULL) + subprocess.run(["podman", "kill", container_id], stdout=subprocess.DEVNULL, check=False) else: print(f"VNC url: http://{forced_host}:7900") yield f"http://{forced_host}:4444" diff --git a/testing/ouia/test_contextselector_ouia.py b/testing/ouia/test_contextselector_ouia.py index 053d59ef..dc0c523a 100644 --- a/testing/ouia/test_contextselector_ouia.py +++ b/testing/ouia/test_contextselector_ouia.py @@ -4,7 +4,9 @@ from widgetastic_patternfly4 import SelectItemNotFound from widgetastic_patternfly4.ouia import ContextSelector -TESTING_PAGE_URL = "https://patternfly-docs-ouia.netlify.app/documentation/react/components/contextselector" # noqa +TESTING_PAGE_URL = ( + "https://patternfly-docs-ouia.netlify.app/documentation/react/components/contextselector" # noqa +) pytestmark = pytest.mark.skip("No OUIA IDs provided on Patternfly testing page") diff --git a/testing/ouia/test_dropdown_ouia.py b/testing/ouia/test_dropdown_ouia.py index ac08dca3..970ea7a0 100644 --- a/testing/ouia/test_dropdown_ouia.py +++ b/testing/ouia/test_dropdown_ouia.py @@ -1,8 +1,7 @@ import pytest from widgetastic.widget import View -from widgetastic_patternfly4 import DropdownItemDisabled -from widgetastic_patternfly4 import DropdownItemNotFound +from widgetastic_patternfly4 import DropdownItemDisabled, DropdownItemNotFound from widgetastic_patternfly4.ouia import Dropdown TESTING_PAGE_URL = ( diff --git a/testing/ouia/test_modal_ouia.py b/testing/ouia/test_modal_ouia.py index 6cdcf6ea..52cd2947 100644 --- a/testing/ouia/test_modal_ouia.py +++ b/testing/ouia/test_modal_ouia.py @@ -1,10 +1,8 @@ import pytest -from widgetastic.widget import Text -from widgetastic.widget import View +from widgetastic.widget import Text, View from widgetastic_patternfly4.modal import ModalItemNotFound -from widgetastic_patternfly4.ouia import Button -from widgetastic_patternfly4.ouia import Modal +from widgetastic_patternfly4.ouia import Button, Modal TESTING_PAGE_URL = "https://patternfly-docs-ouia.netlify.app/documentation/react/components/modal" diff --git a/testing/ouia/test_table_ouia.py b/testing/ouia/test_table_ouia.py index d43e2df2..dddd5cef 100644 --- a/testing/ouia/test_table_ouia.py +++ b/testing/ouia/test_table_ouia.py @@ -15,7 +15,7 @@ ] -@pytest.mark.parametrize("sample", SORT, ids=lambda sample: "{}-{}".format(sample[0], sample[1])) +@pytest.mark.parametrize("sample", SORT, ids=lambda sample: f"{sample[0]}-{sample[1]}") def test_sortable_table(browser, sample): header, order, expected_result = sample diff --git a/testing/test_cardview.py b/testing/test_cardview.py index c3595e4f..0aec3217 100644 --- a/testing/test_cardview.py +++ b/testing/test_cardview.py @@ -1,12 +1,8 @@ import pytest from wait_for import wait_for -from widgetastic.widget import ParametrizedView -from widgetastic.widget import Text +from widgetastic.widget import ParametrizedView, Text -from widgetastic_patternfly4 import CardCheckBox -from widgetastic_patternfly4 import CardForCardGroup -from widgetastic_patternfly4 import CardGroup -from widgetastic_patternfly4 import Dropdown +from widgetastic_patternfly4 import CardCheckBox, CardForCardGroup, CardGroup, Dropdown TESTING_PAGE_URL = "https://patternfly-react.surge.sh/demos/card-view/react-demos/card-view/" diff --git a/testing/test_chipgroup.py b/testing/test_chipgroup.py index e76db788..ad43ae56 100644 --- a/testing/test_chipgroup.py +++ b/testing/test_chipgroup.py @@ -1,11 +1,7 @@ import pytest -from widgetastic.widget import ParametrizedView -from widgetastic.widget import View +from widgetastic.widget import ParametrizedView, View -from widgetastic_patternfly4 import CategoryChipGroup -from widgetastic_patternfly4 import Chip -from widgetastic_patternfly4 import ChipGroup -from widgetastic_patternfly4 import ChipReadOnlyError +from widgetastic_patternfly4 import CategoryChipGroup, Chip, ChipGroup, ChipReadOnlyError TESTING_PAGE_URL = "https://patternfly-react.surge.sh/components/chip-group" diff --git a/testing/test_contextselector.py b/testing/test_contextselector.py index ca2ca489..7fa2943d 100644 --- a/testing/test_contextselector.py +++ b/testing/test_contextselector.py @@ -1,8 +1,7 @@ import pytest from widgetastic.widget import View -from widgetastic_patternfly4 import ContextSelector -from widgetastic_patternfly4 import SelectItemNotFound +from widgetastic_patternfly4 import ContextSelector, SelectItemNotFound TESTING_PAGE_URL = "https://patternfly-react.surge.sh/components/context-selector" diff --git a/testing/test_drawer.py b/testing/test_drawer.py index 1e8f9df9..b46de1fb 100644 --- a/testing/test_drawer.py +++ b/testing/test_drawer.py @@ -1,6 +1,5 @@ import pytest -from widgetastic.widget import Text -from widgetastic.widget import View +from widgetastic.widget import Text, View from widgetastic_patternfly4 import Drawer from widgetastic_patternfly4.button import Button diff --git a/testing/test_dropdown.py b/testing/test_dropdown.py index 4888dcfe..bb697aa2 100644 --- a/testing/test_dropdown.py +++ b/testing/test_dropdown.py @@ -1,11 +1,13 @@ import pytest from widgetastic.widget import View -from widgetastic_patternfly4 import Dropdown -from widgetastic_patternfly4 import DropdownItemDisabled -from widgetastic_patternfly4 import DropdownItemNotFound -from widgetastic_patternfly4 import GroupDropdown -from widgetastic_patternfly4 import SplitButtonDropdown +from widgetastic_patternfly4 import ( + Dropdown, + DropdownItemDisabled, + DropdownItemNotFound, + GroupDropdown, + SplitButtonDropdown, +) TESTING_PAGE_URL = "https://patternfly-react.surge.sh/components/dropdown" @@ -33,8 +35,7 @@ def group_dropdown(browser): return GroupDropdown( browser, locator=( - ".//div[@id='ws-react-c-dropdown-with-groups']" - "/div[contains(@class, 'pf-c-dropdown')]" + ".//div[@id='ws-react-c-dropdown-with-groups']/div[contains(@class, 'pf-c-dropdown')]" ), ) diff --git a/testing/test_duallistselector.py b/testing/test_duallistselector.py index a591a867..467545d1 100644 --- a/testing/test_duallistselector.py +++ b/testing/test_duallistselector.py @@ -1,8 +1,7 @@ import pytest from widgetastic.widget import View -from widgetastic_patternfly4 import DualListSelector -from widgetastic_patternfly4 import SearchDualListSelector +from widgetastic_patternfly4 import DualListSelector, SearchDualListSelector TESTING_PAGE_URL = "https://patternfly-react.surge.sh/components/dual-list-selector" diff --git a/testing/test_formselect.py b/testing/test_formselect.py index 1e456f3a..6a9078b6 100644 --- a/testing/test_formselect.py +++ b/testing/test_formselect.py @@ -1,10 +1,12 @@ import pytest from widgetastic.widget import View -from widgetastic_patternfly4 import FormSelect -from widgetastic_patternfly4 import FormSelectDisabled -from widgetastic_patternfly4 import FormSelectOptionDisabled -from widgetastic_patternfly4 import FormSelectOptionNotFound +from widgetastic_patternfly4 import ( + FormSelect, + FormSelectDisabled, + FormSelectOptionDisabled, + FormSelectOptionNotFound, +) TESTING_PAGE_URL = "https://patternfly-react.surge.sh/components/form-select" diff --git a/testing/test_menu.py b/testing/test_menu.py index 550abb96..e9413015 100644 --- a/testing/test_menu.py +++ b/testing/test_menu.py @@ -1,8 +1,7 @@ import pytest from widgetastic.widget import View -from widgetastic_patternfly4 import Menu -from widgetastic_patternfly4 import MenuItemNotFound +from widgetastic_patternfly4 import Menu, MenuItemNotFound TESTING_PAGE_URL = "https://patternfly-react.surge.sh/components/menu" diff --git a/testing/test_modal.py b/testing/test_modal.py index 1ab94398..5a7dd1d7 100644 --- a/testing/test_modal.py +++ b/testing/test_modal.py @@ -2,8 +2,7 @@ from widgetastic.widget import Text from widgetastic_patternfly4.button import Button -from widgetastic_patternfly4.modal import Modal -from widgetastic_patternfly4.modal import ModalItemNotFound +from widgetastic_patternfly4.modal import Modal, ModalItemNotFound TESTING_PAGE_URL = "https://patternfly-react.surge.sh/components/modal" diff --git a/testing/test_nav.py b/testing/test_nav.py index 5b6275c5..dc921e72 100644 --- a/testing/test_nav.py +++ b/testing/test_nav.py @@ -1,8 +1,7 @@ import pytest from widgetastic.widget import View -from widgetastic_patternfly4 import Navigation -from widgetastic_patternfly4 import NavSelectionNotFound +from widgetastic_patternfly4 import Navigation, NavSelectionNotFound TESTING_PAGE_URL = "https://patternfly-react.surge.sh/components/navigation" diff --git a/testing/test_optionsmenu.py b/testing/test_optionsmenu.py index 22ab21e1..62255fe0 100644 --- a/testing/test_optionsmenu.py +++ b/testing/test_optionsmenu.py @@ -1,8 +1,7 @@ import pytest from widgetastic.widget import View -from widgetastic_patternfly4 import DropdownItemNotFound -from widgetastic_patternfly4 import OptionsMenu +from widgetastic_patternfly4 import DropdownItemNotFound, OptionsMenu TESTING_PAGE_URL = "https://patternfly-react.surge.sh/components/options-menu" diff --git a/testing/test_pagination.py b/testing/test_pagination.py index 4cf1629a..11f83b0b 100644 --- a/testing/test_pagination.py +++ b/testing/test_pagination.py @@ -4,9 +4,7 @@ from wait_for import wait_for from widgetastic.widget import View -from widgetastic_patternfly4 import CompactPagination -from widgetastic_patternfly4 import Pagination -from widgetastic_patternfly4 import PaginationNavDisabled +from widgetastic_patternfly4 import CompactPagination, Pagination, PaginationNavDisabled TESTING_PAGE_URL = "https://patternfly-react.surge.sh/components/pagination" diff --git a/testing/test_select.py b/testing/test_select.py index 57cfd256..085d309a 100644 --- a/testing/test_select.py +++ b/testing/test_select.py @@ -1,9 +1,7 @@ import pytest from widgetastic.widget import View -from widgetastic_patternfly4 import CheckboxSelect -from widgetastic_patternfly4 import Select -from widgetastic_patternfly4 import SelectItemNotFound +from widgetastic_patternfly4 import CheckboxSelect, Select, SelectItemNotFound TESTING_PAGE_URL = "https://patternfly-react.surge.sh/components/select" diff --git a/testing/test_slider.py b/testing/test_slider.py index 214e4bbf..1928044d 100644 --- a/testing/test_slider.py +++ b/testing/test_slider.py @@ -1,9 +1,7 @@ import pytest -from widgetastic.widget import Text -from widgetastic.widget import View +from widgetastic.widget import Text, View -from widgetastic_patternfly4 import InputSlider -from widgetastic_patternfly4 import Slider +from widgetastic_patternfly4 import InputSlider, Slider TESTING_PAGE_URL = "https://patternfly-react.surge.sh/components/slider/" TEST_DATA = { diff --git a/testing/test_switch.py b/testing/test_switch.py index cf080a05..a39b5764 100644 --- a/testing/test_switch.py +++ b/testing/test_switch.py @@ -1,8 +1,7 @@ import pytest from widgetastic.widget import View -from widgetastic_patternfly4 import Switch -from widgetastic_patternfly4 import SwitchDisabled +from widgetastic_patternfly4 import Switch, SwitchDisabled TESTING_PAGE_URL = "https://patternfly-react.surge.sh/components/switch" diff --git a/testing/test_table.py b/testing/test_table.py index 5faf1c3c..b46c9829 100644 --- a/testing/test_table.py +++ b/testing/test_table.py @@ -1,12 +1,13 @@ import pytest -from widgetastic.widget import Checkbox -from widgetastic.widget import View - -from widgetastic_patternfly4 import ColumnNotExpandable -from widgetastic_patternfly4 import CompoundExpandableTable -from widgetastic_patternfly4 import ExpandableTable -from widgetastic_patternfly4 import PatternflyTable -from widgetastic_patternfly4 import RowNotExpandable +from widgetastic.widget import Checkbox, View + +from widgetastic_patternfly4 import ( + ColumnNotExpandable, + CompoundExpandableTable, + ExpandableTable, + PatternflyTable, + RowNotExpandable, +) TESTING_PAGE_URL = "https://patternfly-react.surge.sh/components/table" @@ -34,7 +35,7 @@ ] -@pytest.mark.parametrize("sample", SORT, ids=lambda sample: "{}-{}".format(sample[0], sample[1])) +@pytest.mark.parametrize("sample", SORT, ids=lambda sample: f"{sample[0]}-{sample[1]}") def test_sortable_table(browser, sample): header, order, expected_result = sample table = PatternflyTable( diff --git a/testing/test_tabs.py b/testing/test_tabs.py index 88b392e9..ee9015df 100644 --- a/testing/test_tabs.py +++ b/testing/test_tabs.py @@ -1,5 +1,4 @@ -from widgetastic.widget import Text -from widgetastic.widget import View +from widgetastic.widget import Text, View from widgetastic_patternfly4 import Tab