From 65e830298a72d98566753ed382e09cd97ab7d162 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jiri=20Dan=C4=9Bk?= Date: Fri, 12 Jan 2024 20:01:12 +0100 Subject: [PATCH] Pin Python version to 3.11.x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Why pin the Python version? Because we _can_ put everybody on the same version. This way, we make it less likely different people will hit different issues. ## Why use Python 3.11? It is well established, binary wheels exist for it in PyPI, it is available on UBI 8 and 9, and on Fedora starting with Fedora 37. ## Why say `python = ">=3.11.5, <3.12.0"`? The syntax uses basic math instead of tildes and carets, which not everybody might've learned what they mean. That makes the requirement easier to read and understand. Signed-off-by: Jiri Daněk --- .github/workflows/code_quality.yaml | 5 ++ .github/workflows/dry_run.yml | 9 ++- README.md | 4 +- ods_ci/run_robot_test.sh | 18 +++++ ods_ci/utils/scripts/Sender/EmailSender.py | 14 ++-- ods_ci/utils/scripts/Sender/Sender.py | 4 +- poetry.lock | 80 +--------------------- pyproject.toml | 5 +- 8 files changed, 47 insertions(+), 92 deletions(-) diff --git a/.github/workflows/code_quality.yaml b/.github/workflows/code_quality.yaml index e28fa7883..463e4d98c 100644 --- a/.github/workflows/code_quality.yaml +++ b/.github/workflows/code_quality.yaml @@ -104,8 +104,13 @@ jobs: id: setup-python uses: actions/setup-python@v5 with: + python-version: '3.11' cache: 'poetry' + - name: Configure poetry + run: | + poetry env use "${{ steps.setup-python.outputs.python-path }}" + - run: poetry check --lock - name: Install ruff diff --git a/.github/workflows/dry_run.yml b/.github/workflows/dry_run.yml index 4522b60ea..bdc51adea 100644 --- a/.github/workflows/dry_run.yml +++ b/.github/workflows/dry_run.yml @@ -8,10 +8,17 @@ jobs: steps: - uses: actions/checkout@v3 - + - name: Install Poetry uses: snok/install-poetry@v1 + - name: Set up Python + id: setup-python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + cache: 'poetry' + - name: Execute ods-ci dryrun run: | mv ods_ci/test-variables.yml.example ods_ci/test-variables.yml diff --git a/README.md b/README.md index fe25f0ab6..1c0f5a734 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ and its upstream project, [Open Data Hub](https://opendatahub.io/). # Requirements 1. Linux distribution that supports Selenium automation on top of either a Chromium/Google-Chrome web browser using [ChromeDriver](https://chromedriver.chromium.org) or Firefox web browser using [geckodriver](https://github.com/mozilla/geckodriver): * relevant web driver binaries can be downloaded here: [ChromeDriver](https://googlechromelabs.github.io/chrome-for-testing) or [geckodriver](https://github.com/mozilla/geckodriver/releases) - * the `ChromeDriver` version must match the installed version of Chromium/Google-Chrome, for `geckodriver` see the release notes for paritcular release + * the `ChromeDriver` version must match the installed version of Chromium/Google-Chrome, for `geckodriver` see the release notes for particular release * install your web driver so that it's visible by Robot Framework during tests execution, e.g. into `~/.local/bin` path 2. [Poetry](https://python-poetry.org/docs/#installation) tool installed and added to your `$PATH`. @@ -53,7 +53,7 @@ and its upstream project, [Open Data Hub](https://opendatahub.io/). * This run_robot_test.sh is a wrapper for creating the python virtual environment and running the Robot Framework CLI. * The wrapper script has several arguments and you can find details in the dedicated document file. See [run_args.md](ods_ci/docs/RUN_ARGUMENTS.md) - * As alternative, you can run any of the test cases by creating the python virual environment, install the packages in [poetry.lock](poetry.lock) and running the `robot` command directly + * As alternative, you can run any of the test cases by creating the python virtual environment, install the packages in [poetry.lock](poetry.lock) and running the `robot` command directly # Contributing diff --git a/ods_ci/run_robot_test.sh b/ods_ci/run_robot_test.sh index fd70d69da..c539702d9 100755 --- a/ods_ci/run_robot_test.sh +++ b/ods_ci/run_robot_test.sh @@ -319,6 +319,7 @@ if command -v yq &> /dev/null fi if [[ ${SKIP_INSTALL} -eq 0 ]]; then + # look for pre-created poetry .venv virtenv="${HOME}/.local/ods-ci/.venv" if [[ -d "${virtenv}" ]]; then echo "Using a pre-created virtual environment in '${virtenv}' for poetry to save time." @@ -327,6 +328,23 @@ if [[ ${SKIP_INSTALL} -eq 0 ]]; then else echo "Pre-created virtual environment has not been found in '${virtenv}'. All dependencies will be installed from scratch." fi + # ensure python 3.11 + python=$(poetry env info --executable) + if [[ -n "${python}" ]] && ${python} -c 'import sys; sys.exit(0 if sys.version_info[0:2] == (3, 11) else 1)'; then + echo "Python '${python}' will be used" + else + echo "Python '${python}' is not of the correct version" + python311=$(which python3.11) + if [[ -n "${python311}" ]]; then + echo "Configuring poetry to use Python ${python311}" + poetry env use "${python311}" + else + echo "[ERROR] Python 3.11 was not found!" + echo "Install Python 3.11 on your machine. On Fedora, do 'sudo dnf install -y python3.11-devel'" + echo "then run 'poetry env use /path/to/python3.11' and then try running robot again" + exit 1 + fi + fi poetry --no-interaction install --sync fi diff --git a/ods_ci/utils/scripts/Sender/EmailSender.py b/ods_ci/utils/scripts/Sender/EmailSender.py index 9dd85eecf..c26b14828 100644 --- a/ods_ci/utils/scripts/Sender/EmailSender.py +++ b/ods_ci/utils/scripts/Sender/EmailSender.py @@ -5,7 +5,7 @@ from email.mime.text import MIMEText from email.utils import COMMASPACE, formatdate from os.path import basename -from typing import Any, List, Optional +from typing import Any from Sender import Sender @@ -24,16 +24,16 @@ def __init__(self): self._message = MIMEMultipart() def prepare_payload( - self, text: str = "", attachments: Optional[List[Any]] = None + self, text: str = "", attachments: list[Any] | None = None ) -> None: self._message.attach(MIMEText(text)) if attachments is not None: for filepath in attachments: with open(filepath, "rb") as file: part = MIMEApplication(file.read(), Name=basename(filepath)) - part[ - "Content-Disposition" - ] = 'attachment; filename="%s"' % basename(filepath) + part["Content-Disposition"] = ( + 'attachment; filename="%s"' % basename(filepath) + ) self._message.attach(part) def prepare_header(self): @@ -67,10 +67,10 @@ def set_sender_address(self, sender_address: str) -> None: def get_sender_address(self) -> str: return self._sender_address - def set_receiver_addresses(self, receiver_addresses: List) -> None: + def set_receiver_addresses(self, receiver_addresses: list) -> None: self._receiver_addresses = receiver_addresses - def get_receiver_addresses(self) -> List: + def get_receiver_addresses(self) -> list: return self._receiver_addresses def set_subject(self, subject: str) -> None: diff --git a/ods_ci/utils/scripts/Sender/Sender.py b/ods_ci/utils/scripts/Sender/Sender.py index 5ab75882e..64bceb28f 100644 --- a/ods_ci/utils/scripts/Sender/Sender.py +++ b/ods_ci/utils/scripts/Sender/Sender.py @@ -1,11 +1,11 @@ from abc import ABC, abstractmethod -from typing import Any, List, Optional +from typing import Any class Sender(ABC): @abstractmethod def prepare_payload( - self, text: str = "", attachments: Optional[List[Any]] = None + self, text: str = "", attachments: list[Any] | None = None ) -> None: pass diff --git a/poetry.lock b/poetry.lock index 8b1f0fcc9..f92a56bb9 100644 --- a/poetry.lock +++ b/poetry.lock @@ -121,34 +121,6 @@ files = [ {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, ] -[[package]] -name = "backports-zoneinfo" -version = "0.2.1" -description = "Backport of the standard library zoneinfo module" -optional = false -python-versions = ">=3.6" -files = [ - {file = "backports.zoneinfo-0.2.1-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:da6013fd84a690242c310d77ddb8441a559e9cb3d3d59ebac9aca1a57b2e18bc"}, - {file = "backports.zoneinfo-0.2.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:89a48c0d158a3cc3f654da4c2de1ceba85263fafb861b98b59040a5086259722"}, - {file = "backports.zoneinfo-0.2.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:1c5742112073a563c81f786e77514969acb58649bcdf6cdf0b4ed31a348d4546"}, - {file = "backports.zoneinfo-0.2.1-cp36-cp36m-win32.whl", hash = "sha256:e8236383a20872c0cdf5a62b554b27538db7fa1bbec52429d8d106effbaeca08"}, - {file = "backports.zoneinfo-0.2.1-cp36-cp36m-win_amd64.whl", hash = "sha256:8439c030a11780786a2002261569bdf362264f605dfa4d65090b64b05c9f79a7"}, - {file = "backports.zoneinfo-0.2.1-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:f04e857b59d9d1ccc39ce2da1021d196e47234873820cbeaad210724b1ee28ac"}, - {file = "backports.zoneinfo-0.2.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:17746bd546106fa389c51dbea67c8b7c8f0d14b5526a579ca6ccf5ed72c526cf"}, - {file = "backports.zoneinfo-0.2.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5c144945a7752ca544b4b78c8c41544cdfaf9786f25fe5ffb10e838e19a27570"}, - {file = "backports.zoneinfo-0.2.1-cp37-cp37m-win32.whl", hash = "sha256:e55b384612d93be96506932a786bbcde5a2db7a9e6a4bb4bffe8b733f5b9036b"}, - {file = "backports.zoneinfo-0.2.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a76b38c52400b762e48131494ba26be363491ac4f9a04c1b7e92483d169f6582"}, - {file = "backports.zoneinfo-0.2.1-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:8961c0f32cd0336fb8e8ead11a1f8cd99ec07145ec2931122faaac1c8f7fd987"}, - {file = "backports.zoneinfo-0.2.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e81b76cace8eda1fca50e345242ba977f9be6ae3945af8d46326d776b4cf78d1"}, - {file = "backports.zoneinfo-0.2.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7b0a64cda4145548fed9efc10322770f929b944ce5cee6c0dfe0c87bf4c0c8c9"}, - {file = "backports.zoneinfo-0.2.1-cp38-cp38-win32.whl", hash = "sha256:1b13e654a55cd45672cb54ed12148cd33628f672548f373963b0bff67b217328"}, - {file = "backports.zoneinfo-0.2.1-cp38-cp38-win_amd64.whl", hash = "sha256:4a0f800587060bf8880f954dbef70de6c11bbe59c673c3d818921f042f9954a6"}, - {file = "backports.zoneinfo-0.2.1.tar.gz", hash = "sha256:fadbfe37f74051d024037f223b8e001611eac868b5c5b06144ef4d8b799862f2"}, -] - -[package.extras] -tzdata = ["tzdata"] - [[package]] name = "beautifulsoup4" version = "4.12.2" @@ -204,8 +176,6 @@ mypy-extensions = ">=0.4.3" packaging = ">=22.0" pathspec = ">=0.9.0" platformdirs = ">=2" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} [package.extras] colorama = ["colorama (>=0.4.3)"] @@ -718,7 +688,6 @@ files = [ [package.dependencies] decorator = ">=4.0.0" stevedore = ">=3.0.0" -typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} [[package]] name = "escapism" @@ -768,7 +737,6 @@ files = [ ] [package.dependencies] -"backports.zoneinfo" = {version = "*", markers = "python_version < \"3.9\""} cached-property = "*" defusedxml = ">=0.6.0" dnspython = ">=2.0.0" @@ -1229,7 +1197,6 @@ files = [ ] [package.dependencies] -"backports.zoneinfo" = {version = "*", markers = "python_version < \"3.9\""} convertdate = ">=2.3.0" hijri-converter = "*" korean-lunar-calendar = "*" @@ -1330,24 +1297,6 @@ docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker perf = ["ipython"] testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"] -[[package]] -name = "importlib-resources" -version = "6.1.0" -description = "Read resources from Python packages" -optional = false -python-versions = ">=3.8" -files = [ - {file = "importlib_resources-6.1.0-py3-none-any.whl", hash = "sha256:aa50258bbfa56d4e33fbd8aa3ef48ded10d1735f11532b8df95388cc6bdb7e83"}, - {file = "importlib_resources-6.1.0.tar.gz", hash = "sha256:9d48dcccc213325e810fd723e7fbb45ccb39f6cf5c31f00cf2b965f5f10f3cb9"}, -] - -[package.dependencies] -zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff", "zipp (>=3.17)"] - [[package]] name = "iniconfig" version = "2.0.0" @@ -1536,9 +1485,7 @@ files = [ [package.dependencies] attrs = ">=22.2.0" -importlib-resources = {version = ">=1.4.0", markers = "python_version < \"3.9\""} jsonschema-specifications = ">=2023.03.6" -pkgutil-resolve-name = {version = ">=1.3.10", markers = "python_version < \"3.9\""} referencing = ">=0.28.4" rpds-py = ">=0.7.1" @@ -1558,7 +1505,6 @@ files = [ ] [package.dependencies] -importlib-resources = {version = ">=1.4.0", markers = "python_version < \"3.9\""} referencing = ">=0.28.0" [[package]] @@ -1618,7 +1564,6 @@ requests-toolbelt = ">=0.8.0,<1" strip-hints = ">=0.1.8,<1" tabulate = ">=0.8.6,<1" typer = ">=0.3.2,<1.0" -typing-extensions = {version = ">=3.7.4,<5", markers = "python_version < \"3.9\""} uritemplate = ">=3.0.1,<4" urllib3 = "<2" @@ -2066,7 +2011,6 @@ files = [ [package.dependencies] mypy-extensions = ">=1.0.0" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} typing-extensions = ">=4.1.0" [package.extras] @@ -2619,17 +2563,6 @@ files = [ docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"] tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] -[[package]] -name = "pkgutil-resolve-name" -version = "1.3.10" -description = "Resolve a name to an object." -optional = false -python-versions = ">=3.6" -files = [ - {file = "pkgutil_resolve_name-1.3.10-py3-none-any.whl", hash = "sha256:ca27cc078d25c5ad71a9de0a7a330146c4e014c2462d9af19c6b828280649c5e"}, - {file = "pkgutil_resolve_name-1.3.10.tar.gz", hash = "sha256:357d6c9e6a755653cfd78893817c0853af365dd51ec97f3d358a819373bbd174"}, -] - [[package]] name = "platformdirs" version = "3.8.1" @@ -3092,9 +3025,6 @@ files = [ {file = "pypdf-3.16.2.tar.gz", hash = "sha256:6e000281fd0f4cd32e6f1e75b05af0b6c0fbbd9777fa9a8e9d86e34cda65419d"}, ] -[package.dependencies] -typing_extensions = {version = ">=3.7.4.3", markers = "python_version < \"3.10\""} - [package.extras] crypto = ["PyCryptodome", "cryptography"] dev = ["black", "flit", "pip-tools", "pre-commit (<2.18.0)", "pytest-cov", "pytest-socket", "pytest-timeout", "wheel"] @@ -3178,11 +3108,9 @@ files = [ [package.dependencies] colorama = {version = "*", markers = "sys_platform == \"win32\""} -exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" pluggy = ">=0.12,<2.0" -tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] @@ -3381,7 +3309,6 @@ files = [ ] [package.dependencies] -"backports.zoneinfo" = {version = "*", markers = "python_version >= \"3.6\" and python_version < \"3.9\""} tzdata = {version = "*", markers = "python_version >= \"3.6\""} [[package]] @@ -3646,7 +3573,6 @@ files = [ [package.dependencies] markdown-it-py = ">=2.2.0" pygments = ">=2.13.0,<3.0.0" -typing-extensions = {version = ">=4.0.0,<5.0", markers = "python_version < \"3.9\""} [package.extras] jupyter = ["ipywidgets (>=7.5.1,<9)"] @@ -4617,7 +4543,6 @@ files = [ [package.dependencies] attrs = ">=20.1.0" cffi = {version = ">=1.14", markers = "os_name == \"nt\" and implementation_name != \"pypy\""} -exceptiongroup = {version = ">=1.0.0rc9", markers = "python_version < \"3.11\""} idna = "*" outcome = "*" sniffio = "*" @@ -4714,7 +4639,6 @@ files = [ ] [package.dependencies] -"backports.zoneinfo" = {version = "*", markers = "python_version < \"3.9\""} pytz-deprecation-shim = "*" tzdata = {version = "*", markers = "platform_system == \"Windows\""} @@ -5046,5 +4970,5 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" -python-versions = "^3.8.1" -content-hash = "137a7000354cc3d046532c81896fecb73820acd4b55a82f0f48c6980eece8111" +python-versions = ">=3.11.5, <3.12.0" +content-hash = "8e41a6db77242aa6dc58d96f16709ddc0bdfe16dc2f315a53c10a66d2d0ec3d3" diff --git a/pyproject.toml b/pyproject.toml index 1364bce41..a37954122 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,8 +6,9 @@ authors = ["RHODS QE "] readme = "README.md" packages = [{include = "ods_ci"}] +# https://python-poetry.org/docs/dependency-specification [tool.poetry.dependencies] -python = "^3.8.1" +python = ">=3.11.5, <3.12.0" reportportal-client = "^5.2.5" robotframework = "^6" robotframework-debuglibrary = ">=2.0.0" @@ -47,7 +48,7 @@ profile = "black" line_length = 88 # align with black's default [tool.ruff] -target-version = "py38" +target-version = "py311" line-length = 88 # align with black's default # https://docs.astral.sh/ruff/rules