From 585fbdf28fa061acebf6736ee671c9b910b9b0b8 Mon Sep 17 00:00:00 2001 From: Bernhard Kaindl Date: Mon, 29 Apr 2024 12:00:00 +0200 Subject: [PATCH 1/4] CA-390883: python3/tests: Fix pylint and pyright warnings Signed-off-by: Bernhard Kaindl --- python3/bin/hfx_filename | 8 +++++++- python3/libexec/nbd_client_manager.py | 2 +- python3/libexec/usb_reset.py | 2 +- python3/libexec/usb_scan.py | 9 ++++++--- python3/tests/test_observer.py | 5 +++++ python3/tests/test_perfmon.py | 2 ++ python3/tests/test_usb_scan.py | 11 +++++------ 7 files changed, 27 insertions(+), 12 deletions(-) diff --git a/python3/bin/hfx_filename b/python3/bin/hfx_filename index dd8677fc499..28fb05bbc78 100755 --- a/python3/bin/hfx_filename +++ b/python3/bin/hfx_filename @@ -14,8 +14,14 @@ # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# pylint: disable=redefined-outer-name +# pyright: reportFunctionMemberAccess=false +# pyright: reportOptionalMemberAccess=false, reportAttributeAccessIssue=false -import sys, socket, urllib.request, XenAPI +import sys +import socket + +import XenAPI db_url = "/remote_db_access" diff --git a/python3/libexec/nbd_client_manager.py b/python3/libexec/nbd_client_manager.py index e30477316d8..0f77e69b12e 100644 --- a/python3/libexec/nbd_client_manager.py +++ b/python3/libexec/nbd_client_manager.py @@ -136,7 +136,7 @@ def _find_unused_nbd_device(): return nbd_device # If there are 1000 nbd devices (unlikely) and all are connected - raise NbdDeviceNotFound(nbd_device) + raise NbdDeviceNotFound(nbd_device) # pyright:ignore[reportPossiblyUnboundVariable] def _wait_for_nbd_device(nbd_device, connected): deadline = datetime.now() + timedelta(minutes=MAX_DEVICE_WAIT_MINUTES) diff --git a/python3/libexec/usb_reset.py b/python3/libexec/usb_reset.py index 82a690bcea0..e29732834fb 100755 --- a/python3/libexec/usb_reset.py +++ b/python3/libexec/usb_reset.py @@ -132,7 +132,7 @@ def load_device_ids(device): # ignore and continue log.warning("Failed to remove device ids: {}".format(str(e))) - return uid, gid + return uid, gid # pyright: ignore[reportPossiblyUnboundVariable] # pragma: no cover # throw IOError, ValueError diff --git a/python3/libexec/usb_scan.py b/python3/libexec/usb_scan.py index e940aa626f5..f6217ea09ec 100755 --- a/python3/libexec/usb_scan.py +++ b/python3/libexec/usb_scan.py @@ -21,6 +21,8 @@ # 2. check if device can be passed through based on policy file # 3. return the device info to XAPI in json format +# pylint: disable=redefined-outer-name +# pyright: reportPossiblyUnboundVariable=false, reportAttributeAccessIssue=false import abc import argparse @@ -71,7 +73,7 @@ def __init__(self, node): def get_node(self): return self.node - def __hash__(self): + def __hash__(self): # pyright:ignore[reportIncompatibleVariableOverride] return hash(self.node) def __eq__(self, other): @@ -109,14 +111,14 @@ def _is_class_hub(self, key_class): return cls is not None and hex_equal(__VALUE_CLASS_HUB, cls) @abc.abstractmethod - def is_class_hub(self): + def is_class_hub(self) -> bool: """check if this belongs to a hub :return: bool, if this belongs to a hub """ @abc.abstractmethod - def is_child_of(self, parent): + def is_child_of(self, parent) -> bool: """check if this is a child of parent :param parent:(UsbObject) the parent to check against @@ -282,6 +284,7 @@ def __init__(self, node, props): if props.get(p) is not None: self[p] = props.get(p).decode() + # pylint: disable-next=useless-parent-delegation # This parent call is superfluous def debug_str(self, level=0): return super().debug_str(level) diff --git a/python3/tests/test_observer.py b/python3/tests/test_observer.py index 9464efbc3e3..a7e14f6174e 100644 --- a/python3/tests/test_observer.py +++ b/python3/tests/test_observer.py @@ -46,6 +46,11 @@ def init_tracing_and_run_simple_method(self, read_data): with patch(OBSERVER_OPEN, mock_open(read_data=read_data)): span, _ = observer._init_tracing([TEST_OBSERVER_CONF], ".") + # If packages are not installed, raise a helpful error message + if span == observer._span_noop: + err = "Look for: missing opentelemetry dependencies: No module named " + raise AssertionError("Dependency of observer.py is not installed: " + err) + simple_method = span(self.simple_method) self.assertEqual(simple_method(), 5) diff --git a/python3/tests/test_perfmon.py b/python3/tests/test_perfmon.py index 9d638f4fab4..c133a1171ac 100644 --- a/python3/tests/test_perfmon.py +++ b/python3/tests/test_perfmon.py @@ -3,6 +3,8 @@ This module provides unittest for perfmon """ +# pyright: reportAttributeAccessIssue=false + import sys import math import unittest diff --git a/python3/tests/test_usb_scan.py b/python3/tests/test_usb_scan.py index f63e4bb8f10..bf0bad03fef 100644 --- a/python3/tests/test_usb_scan.py +++ b/python3/tests/test_usb_scan.py @@ -25,8 +25,7 @@ def __init__(self, device): self.d = device.get_attr() def __iter__(self): # pragma: no cover - for name in self.d: - yield name + yield from self.d def __len__(self): # pragma: no cover return len(self.d) @@ -54,8 +53,7 @@ def attributes(self): return MocDeviceAttrs(self) def __iter__(self): # pragma: no cover - for name in self.get_prop(): - yield name + yield from self.get_prop() def __len__(self): # pragma: no cover return len(self.get_prop()) @@ -64,7 +62,7 @@ def __getitem__(self, name): return self.get_prop().get(name) -class MocEnumerator(object): +class MocEnumerator(): def __init__(self, ds): self.ds = ds @@ -73,7 +71,7 @@ def __iter__(self): yield MocDevice(d) -class MocContext(object): +class MocContext(): def __init__(self, devices, interfaces): self.devices = devices self.interfaces = interfaces @@ -85,6 +83,7 @@ def list_devices(self, **kwargs): return MocEnumerator(self.devices) elif dev_type == "usb_interface": return MocEnumerator(self.interfaces) + raise AssertionError(f"unexpected {dev_type}") # pragma: no cover def mock_setup(mod, devices, interfaces, path): From e846a782ed98d9d9ac3e83efa81d663f8ff5dca9 Mon Sep 17 00:00:00 2001 From: Bernhard Kaindl Date: Wed, 8 May 2024 12:00:00 +0200 Subject: [PATCH 2/4] CA-390883: pyproject.toml: Add config for pytest & other local checks Signed-off-by: Bernhard Kaindl --- pyproject.toml | 135 ++++++++++++++++++++++++---------- python3/stubs/XenAPI.pyi | 85 +++++++++++++++++++++ python3/stubs/xcp/branding.py | 38 ++++++++++ python3/stubs/xcp/logger.pyi | 6 ++ pytype_reporter.py | 18 +++-- 5 files changed, 237 insertions(+), 45 deletions(-) create mode 100644 python3/stubs/XenAPI.pyi create mode 100644 python3/stubs/xcp/branding.py create mode 100644 python3/stubs/xcp/logger.pyi diff --git a/pyproject.toml b/pyproject.toml index 739597edef4..4d67311696c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,6 +27,25 @@ repository = "https://github.com/xapi-project/xen-api" [tool.black] line-length = 88 + +# ----------------------------------------------------------------------------- +# Coverage.py - https://coverage.readthedocs.io/en/coverage-5.5/config.html +# ----------------------------------------------------------------------------- + +[tool.coverage.report] +# fail_under: minimum code coverage percentage +# skip_covered: if fully covered files should be reported +# exclude_lines: lines to not require to be covered +fail_under = 50 +skip_covered = true +exclude_lines = [ + "pragma: no cover", + "if TYPE_CHECKING:", + "pass", + "raise NbdDeviceNotFound", # python3/libexec/usb_scan.py +] + + [tool.isort] line_length = 88 py_version = 27 @@ -40,6 +59,8 @@ disable = [ "missing-module-docstring", "missing-class-docstring", "consider-using-f-string", + "too-few-public-methods", + "too-many-public-methods", "too-many-branches", "too-many-arguments", "broad-exception-caught", @@ -82,54 +103,94 @@ disallow_any_unimported = true disallow_subclassing_any = true +# ----------------------------------------------------------------------------- +# Pyright static analysis and Pylance IDE language plugin of VSCode +# https://microsoft.github.io/pyright/#/configuration +# ----------------------------------------------------------------------------- + +[tool.pyright] +# include: directories to include in checking +# strict: paths for which strict checking works +# typeCheckingMode: set the standard type checking mode +include = ["python3", "ocaml/xcp-rrdd"] +strict = ["python3/tests/observer"] +pythonPlatform = "Linux" +typeCheckingMode = "standard" +reportMissingImports = false +pythonVersion = "3.6" +exclude = [ + "ocaml/xcp-rrdd/scripts/rrdd/rrdd.py", + "ocaml/xcp-rrdd/scripts/rrdd/rrdd-example.py", + "python3/packages/observer.py", +] + + +# ----------------------------------------------------------------------------- +# pytest: helps you write better programs - https://docs.pytest.org +# ----------------------------------------------------------------------------- + +[tool.pytest.ini_options] +# ----------------------------------------------------------------------------- +# Options to enable for pytest by default: +# -v show what happens +# -rA show summary after running tests +# --cov=python3 measure coverage of the python3 directory +# --cov-fail-under minimum coverage percentage +# --cov-report=term-missing show missing lines in the coverage report +# --cov-report=html: generate an HTML coverage report(for viewing) +# --cov-report=xml: generate an XML coverage report(for upload) +# ----------------------------------------------------------------------------- +addopts = """ +-v -rA --cov=python3 --cov=scripts --cov-fail-under=50 +--cov-report=html:.git/coverage --cov-report=term-missing +--cov-report=xml:.git/coverage3.11.xml +""" + +# ----------------------------------------------------------------------------- +# Other pytest config options: +# log_cli: show logger messages +# log_cli_level: log level to show +# python_files: pattern for test files +# python_functions: pattern for test functions +# testpaths: directories to search for tests +# minversion: this config requires pytest>=7 to configure pythonpath +# pythonpath: path to stub files and typing stubs for tests +# xfail_strict: require to remove pytext.xfail marker when test is fixed +# required_plugins: require that these plugins are installed before testing +# ----------------------------------------------------------------------------- +testpaths = ["python3", "scripts", "ocaml/xcp-rrdd"] +required_plugins = ["pytest-cov", "pytest-mock"] +log_cli_level = "INFO" +log_cli = true +minversion = "7.0" +pythonpath = "python3/stubs" +python_files = ["test_*.py", "it_*.py"] +python_functions = ["test_", "it_", "when_"] +xfail_strict = true + + [tool.pytype_reporter] -default_branch = "master" +default_branch = "feature/py3" discard_messages_matching = [ "Couldn't import pyi for 'xml.dom.minidom'", "No attribute '.*' on RRDContentHandler", "No attribute 'group' on None", "No Node.TEXT_NODE in module xml.dom.minidom, referenced from 'xml.dom.expatbuilder'" ] -expected_to_fail = [ - # Need 2to3 -w and maybe a few other minor updates: - "scripts/hatests", - "scripts/backup-sr-metadata.py", - "scripts/restore-sr-metadata.py", - # SSLSocket.send() only accepts bytes, not unicode string as argument: - "scripts/examples/python/exportimport.py", - # Other fixes needed: - "scripts/examples/python/mini-xenrt.py", - "scripts/examples/python/XenAPI/XenAPI.py", - "scripts/examples/python/monitor-unwanted-domains.py", - "scripts/examples/python/shell.py", - "scripts/examples/smapiv2.py", - "scripts/static-vdis", - "scripts/plugins/extauth-hook-AD.py", -] +expected_to_fail = [] +# ----------------------------------------------------------------------------- +# pytype: Google's static type analyzer - https://google.github.io/pytype/ +# ----------------------------------------------------------------------------- + [tool.pytype] inputs = [ - "scripts/static-vdis", - "scripts/Makefile", - "scripts/generate-iscsi-iqn", - "scripts/hatests", - "scripts/host-display", - "scripts/mail-alarm", - "scripts/print-custom-templates", - "scripts/probe-device-for-file", - "scripts/xe-reset-networking", - "scripts/xe-scsi-dev-map", - "scripts/examples/python", - "scripts/yum-plugins", - "scripts/*.py", - "python3/packages/*.py", - - # Python 3 "python3/bin/hfx_filename", "python3/bin/perfmon", "python3/bin/*.py", "python3/libexec/*.py", + "python3/packages/*.py", # To be added later, # when converted to Python3-compatible syntax: @@ -138,12 +199,8 @@ inputs = [ # "ocaml/xapi-storage/python", ] disable = [ - "import-error", # xenfsimage, xcp.bootloader. xcp.cmd - "ignored-abstractmethod", + "import-error", # opentelemetry packages "ignored-metaclass", - # https://github.com/google/pytype/issues/1130, - # https://github.com/google/pytype/issues/1485: - "pyi-error", ] platform = "linux" -pythonpath = "scripts/examples/python:.:scripts:scripts/plugins:scripts/examples" +pythonpath = "python3/stubs:." diff --git a/python3/stubs/XenAPI.pyi b/python3/stubs/XenAPI.pyi new file mode 100644 index 00000000000..4590e614814 --- /dev/null +++ b/python3/stubs/XenAPI.pyi @@ -0,0 +1,85 @@ +""" +Stub for the XenAPI module: https://xapi-project.github.io/xen-api/overview.html +""" + + +import http.client as httplib +import xmlrpc.client as xmlrpclib +from _typeshed import Incomplete as Incomplete + +translation: Incomplete +API_VERSION_1_1: str +API_VERSION_1_2: str + + +class Failure(Exception): + details: Incomplete + + def __init__(self, details) -> None: ... + + +class UDSHTTPConnection(httplib.HTTPConnection): + sock: Incomplete + + def connect(self) -> None: ... + + +class UDSTransport(xmlrpclib.Transport): + def add_extra_header(self, key, value) -> None: ... + + # def make_connection(self, host) -> None: ... + + +def notimplemented(name, *args, **kwargs) -> None: ... + + +class _Dispatcher: + """A dispatcher for the Xen-API. It is used to call methods on the server""" + def __init__(self, API_version, send, name) -> None: ... + def __getattr__(self, name) -> None: ... + def __call__(self, *args) -> None: ... + def login_with_password(self, username, password, version, client_name) -> None: + """Authenticate the session with the XenAPI server.""" + def logout(self) -> None: + """End the session with the XenAPI server.""" + session: Incomplete + secret: Incomplete + SR: Incomplete + PBD: Incomplete + pool: Incomplete + VM: Incomplete + + +class Session(xmlrpclib.ServerProxy): + """A server proxy and session manager for communicating with xapi using + the Xen-API. + + Example: + + session = Session('http://localhost/') + session.login_with_password('me', 'mypassword', '1.0', 'xen-api-scripts-xenapi.py') + session.xenapi.VM.start(vm_uuid) + session.xenapi.session.logout() + """ + + transport: Incomplete + last_login_method: Incomplete + last_login_params: Incomplete + API_version: Incomplete + xenapi: _Dispatcher + + def __init__( + self, + uri, + transport: Incomplete | None = ..., + encoding: Incomplete | None = ..., + verbose: int = ..., + allow_none: int = ..., + ignore_ssl: bool = ..., + ) -> None: ... + def xenapi_request(self, methodname, params) -> None: ... + + # def __getattr__(self, name) -> None: ... + + +def xapi_local() -> Session: ... diff --git a/python3/stubs/xcp/branding.py b/python3/stubs/xcp/branding.py new file mode 100644 index 00000000000..30ff69600bf --- /dev/null +++ b/python3/stubs/xcp/branding.py @@ -0,0 +1,38 @@ +# Example xcp.branding module as test stub for test mail-alarm. +# python3/stubs is added to PYTHONPATH by pyproject.toml +COPYRIGHT_YEARS = '2009-2024' +PRODUCT_BRAND = 'XenServer' +PRODUCT_BRAND_DASHED = 'xenserver' +PRODUCT_NAME = 'xenenterprise' +COMPANY_NAME_LEGAL = 'Cloud Software Group, Inc.' +COMPANY_NAME_SHORT = 'Cloud Software Group' +COMPANY_DOMAIN = 'xenserver.com' +COMPANY_PRODUCT_BRAND = 'XenServer' +BRAND_CONSOLE = 'XenCenter' +BRAND_SERVER = 'XenServer Host' +BRAND_VDI = 'Virtual Desktops' +BRAND_CONSOLE_URL = 'https://www.xenserver.com/downloads' +ISO_PV_TOOLS_COPYRIGHT = 'Cloud Software Group, Inc. 2009-2024' +ISO_PV_TOOLS_LABEL = 'XenServer VM Tools' +COMPANY_NAME = 'Cloud Software Group, Inc.' +COMPANY = 'Cloud Software Group' +COMPANY_WEBSITE = 'www.xenserver.com' +PLATFORM_NAME = 'XCP' +PLATFORM_ORGANISATION = 'xen.org' +PLATFORM_WEBSITE = 'www.xen.org' +BRAND_GUEST = 'Virtual Machine' +BRAND_GUESTS = 'Virtual Machines' +BRAND_GUEST_SHORT = 'VM' +BRAND_GUESTS_SHORT = 'VMs' +BRAND_SERVERS = 'XenServer Hosts' +ISO_PV_TOOLS_PUBLISHER = 'Cloud Software Group, Inc.' +PRODUCT_MAJOR_VERSION = '8' +PRODUCT_MINOR_VERSION = '4' +PRODUCT_MICRO_VERSION = '0' +PRODUCT_VERSION_TEXT = '8' +PRODUCT_VERSION_TEXT_SHORT = '8' +PLATFORM_MAJOR_VERSION = '3' +PLATFORM_MINOR_VERSION = '4' +PLATFORM_MICRO_VERSION = '0' +PLATFORM_VERSION = '3.4.0' +PRODUCT_VERSION = '8.4.0' diff --git a/python3/stubs/xcp/logger.pyi b/python3/stubs/xcp/logger.pyi new file mode 100644 index 00000000000..f4aa2dab371 --- /dev/null +++ b/python3/stubs/xcp/logger.pyi @@ -0,0 +1,6 @@ +# Minimal stub for xcp.logger module +def debug(*al, **ad) -> None: ... +def error(*al, **ad) -> None: ... +def warning(*al, **ad) -> None: ... +def logToStdout(level) -> bool: ... +def logToSyslog(level) -> bool: ... diff --git a/pytype_reporter.py b/pytype_reporter.py index 8207053d7ec..5be487aedc8 100755 --- a/pytype_reporter.py +++ b/pytype_reporter.py @@ -599,13 +599,19 @@ def main(): config_file = "pyproject.toml" config = load_config(config_file, basename(__file__)) config.setdefault("expected_to_fail", []) - debug("Expected to fail: %s", ", ".join(config["expected_to_fail"])) - changed_but_in_expected_to_fail = git_diff( - "--name-only", - find_branch_point(config), - *config["expected_to_fail"], - ).splitlines() + + # Fixed to work also when expected_to_fail is empty: + + changed_but_in_expected_to_fail = [] + if config["expected_to_fail"]: + debug("Expected to fail: %s", ", ".join(config["expected_to_fail"])) + + changed_but_in_expected_to_fail = git_diff( + "--name-only", + find_branch_point(config), + *config["expected_to_fail"], + ).splitlines() if check_only_reverts_from_branch_point(config, changed_but_in_expected_to_fail): return run_pytype_and_generate_summary(config) From ea6700c9980191021c75797fef4a0f187f906e08 Mon Sep 17 00:00:00 2001 From: Bernhard Kaindl Date: Wed, 8 May 2024 12:00:00 +0200 Subject: [PATCH 3/4] CA-390883: .pre-commit-config.yaml: Add venvs for running local tests Signed-off-by: Bernhard Kaindl --- .pre-commit-config.yaml | 101 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 100 insertions(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0ca5ef37fee..668b4190ce1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,6 +14,8 @@ # pre-commit run -av --hook-stage pre-push # default_stages: [commit, push] +default_language_version: + python: python3.11 repos: # Recommendation for a minimal git pre-commit hook: # https://github.com/pre-commit/pre-commit-hooks/blob/main/README.md: @@ -29,6 +31,95 @@ repos: - id: check-executables-have-shebangs exclude: ocaml + +# Improve Python formatting incrementally: +# https://dev.to/akaihola/improving-python-code-incrementally-3f7a +# +# darker checks if staged python changes are formatted according using +# the PEP8-aligned black formatter. It also checks if the imports are sorted. +# +# It is a good idea to run this before committing, and it is also run in the +# GitHub Workflow. +# +# Note: darker only checks the changes in files ending in .py! +# Python scripts that don't end in .py should be renamed to have the .py extension +# when moving them to python3/bin. +# (remove the .py extension in the Makefile when installing the file) +# +- repo: https://github.com/akaihola/darker + rev: 1.7.3 + hooks: + - id: darker + files: python3/ + name: check changes in Python3 tree using darker and isort + args: [--diff, --skip-string-normalization, --isort, -tpy36] + additional_dependencies: [isort] + +# +# Run pytest and diff-cover to check that the new /python3 test suite in passes. +# This hook uses a local venv containing the required dependencies. When adding +# new dependencies, they should be added to the additional_dependencies below. +# +- repo: local + hooks: + - id: pytest + files: python3/ + name: check that the Python3 test suite in passes + entry: env PYTHONDEVMODE=yes sh -c 'python3 -m pytest -vv && + diff-cover --ignore-whitespace --compare-branch=origin/feature/py3 + --show-uncovered --html-report .git/coverage-diff.html + --fail-under 50 .git/coverage3.11.xml' + require_serial: true + pass_filenames: false + language: python + types: [python] + additional_dependencies: + - coverage + - diff-cover + - future + - opentelemetry-api + - opentelemetry-exporter-zipkin-json + - opentelemetry-sdk + - pytest-coverage + - pytest-mock + - mock + - wrapt + - XenAPI + + +- repo: https://github.com/RobertCraigie/pyright-python + rev: v1.1.361 + hooks: + - id: pyright + name: check that python3 tree passes pyright/VSCode check + files: python3/ + additional_dependencies: + - mock + - opentelemetry-api + - opentelemetry-exporter-zipkin-json + - opentelemetry-sdk + - pytest + - pyudev + - XenAPI + + +# Check that pylint passes for the changes in new /python3 code. +- repo: local + hooks: + - id: pylint + files: python3/ + stages: [push] + name: check that changes to python3 tree pass pylint + entry: diff-quality --violations=pylint + --ignore-whitespace --compare-branch=origin/feature/py3 + pass_filenames: false + language: python + types: [python] + additional_dependencies: [diff-cover, pylint, pytest] + + +# pre-push hook (it only runs if you install pre-commit as a pre-push hook): +# It can be manually tested using: `pre-commit run -av --hook-stage push` # Recommendation for a minimal git pre-push hook: # While using pre-commit yields great results, it # is "not fast". Therefore only run it pre-push, @@ -53,4 +144,12 @@ repos: # developers have such version installed, it can be configured here: # language_version: python3.11 require_serial: true - additional_dependencies: [pandas, pytype] + additional_dependencies: + - future + - opentelemetry-api + - opentelemetry-exporter-zipkin-json + - opentelemetry-sdk + - pandas + - pytest + - pytype + files: python3/ From b747121ce83a47e4ae752eebfb97de15483fb390 Mon Sep 17 00:00:00 2001 From: Bernhard Kaindl Date: Tue, 7 May 2024 12:00:00 +0200 Subject: [PATCH 4/4] CA-390883: Simplify GitHub Workflow to re-use venvs from pre-commit Signed-off-by: Bernhard Kaindl --- .github/workflows/main.yml | 30 ++++-------------------------- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index da0e2bd35a2..9efd41207fc 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -15,6 +15,8 @@ jobs: python-test: name: Python tests runs-on: ubuntu-22.04 + env: + PYTHONDEVMODE: yes strategy: fail-fast: false matrix: @@ -45,40 +47,16 @@ jobs: env: SKIP: no-commit-to-branch - - name: Install dependencies only needed for python 2 - if: ${{ matrix.python-version == '2.7' }} - run: pip install enum - - - name: Install dependencies only needed for python 3 - if: ${{ matrix.python-version != '2.7' }} - run: pip install pandas pytype toml wrapt - - - name: Install common dependencies for Python ${{matrix.python-version}} - run: pip install future mock pytest-coverage pytest-mock - - name: Run Pytest for python 2 and get code coverage for Codecov if: ${{ matrix.python-version == '2.7' }} run: > + pip install enum future mock pytest-coverage pytest-mock && pytest --cov=ocaml/xcp-rrdd scripts/ ocaml/xcp-rrdd -vv -rA --junitxml=.git/pytest${{matrix.python-version}}.xml --cov-report term-missing --cov-report xml:.git/coverage${{matrix.python-version}}.xml - env: - PYTHONDEVMODE: yes - - - name: Run Pytest for python 3 and get code coverage for Codecov - if: ${{ matrix.python-version != '2.7' }} - run: > - pytest - --cov=python3/ - python3/tests -vv -rA - --junitxml=.git/pytest${{matrix.python-version}}.xml - --cov-report term-missing - --cov-report xml:.git/coverage${{matrix.python-version}}.xml - env: - PYTHONDEVMODE: yes - name: Upload Python ${{matrix.python-version}} coverage report to Codecov uses: codecov/codecov-action@v3 @@ -101,7 +79,7 @@ jobs: - name: Run pytype checks if: ${{ matrix.python-version != '2.7' }} - run: ./pytype_reporter.py + run: pip install pandas pytype toml && ./pytype_reporter.py env: PR_NUMBER: ${{ github.event.number }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}