diff --git a/.github/workflows/cron-ci.yaml b/.github/workflows/cron-ci.yaml index 68ef4dea47a..a481e71de06 100644 --- a/.github/workflows/cron-ci.yaml +++ b/.github/workflows/cron-ci.yaml @@ -12,7 +12,7 @@ on: name: Periodic checks/tasks env: - CARGO_ARGS: --no-default-features --features stdlib,importlib,encodings,ssl-rustls,jit + CARGO_ARGS: --no-default-features --features stdlib,importlib,stdio,encodings,ssl-rustls,jit,host_env PYTHON_VERSION: "3.14.3" jobs: @@ -35,7 +35,7 @@ jobs: python-version: ${{ env.PYTHON_VERSION }} - run: sudo apt-get update && sudo apt-get -y install lcov - name: Run cargo-llvm-cov with Rust tests. - run: cargo llvm-cov --no-report --workspace --exclude rustpython_wasm --exclude rustpython-compiler-source --exclude rustpython-venvlauncher --verbose --no-default-features --features stdlib,importlib,encodings,ssl-rustls,jit + run: cargo llvm-cov --no-report --workspace --exclude rustpython_wasm --exclude rustpython-compiler-source --exclude rustpython-venvlauncher --verbose --no-default-features --features stdlib,importlib,stdio,encodings,ssl-rustls,jit,host_env - name: Run cargo-llvm-cov with Python snippets. run: python scripts/cargo-llvm-cov.py continue-on-error: true @@ -48,7 +48,7 @@ jobs: if: ${{ github.event_name != 'pull_request' }} uses: codecov/codecov-action@v5 with: - file: ./codecov.lcov + files: ./codecov.lcov testdata: name: Collect regression test data @@ -170,12 +170,12 @@ jobs: - name: restructure generated files run: | cd ./target/criterion/reports - find -type d -name cpython | xargs rm -rf - find -type d -name rustpython | xargs rm -rf - find -mindepth 2 -maxdepth 2 -name violin.svg | xargs rm -rf - find -type f -not -name violin.svg | xargs rm -rf - for file in $(find -type f -name violin.svg); do mv $file $(echo $file | sed -E "s_\./([^/]+)/([^/]+)/violin\.svg_./\1/\2.svg_"); done - find -mindepth 2 -maxdepth 2 -type d | xargs rm -rf + find . -type d -name cpython -print0 | xargs -0 rm -rf + find . -type d -name rustpython -print0 | xargs -0 rm -rf + find . -mindepth 2 -maxdepth 2 -name violin.svg -print0 | xargs -0 rm -rf + find . -type f -not -name violin.svg -print0 | xargs -0 rm -rf + find . -type f -name violin.svg -exec sh -c 'for file; do mv "$file" "$(echo "$file" | sed -E "s_\./([^/]+)/([^/]+)/violin\.svg_./\1/\2.svg_")"; done' _ {} + + find . -mindepth 2 -maxdepth 2 -type d -print0 | xargs -0 rm -rf cd .. mv reports/* . rmdir reports diff --git a/extra_tests/custom_text_test_runner.py b/extra_tests/custom_text_test_runner.py index afec493a66c..3457bdfd0e4 100644 --- a/extra_tests/custom_text_test_runner.py +++ b/extra_tests/custom_text_test_runner.py @@ -38,6 +38,16 @@ from unittest.runner import registerResult, result +def _get_method_dict(test): + """Get the __dict__ of the underlying function for a test method. + + Works for both bound methods (__func__.__dict__) and plain functions. + """ + method = getattr(test, test._testMethodName) + func = getattr(method, "__func__", method) + return func.__dict__ + + class TablePrinter(object): # Modified from https://github.com/agramian/table-printer, same license as above "Print a list of dicts as a table" @@ -325,9 +335,7 @@ def startTest(self, test): self.stream.writeln("TEST SUITE: %s" % self.suite) self.stream.writeln("Description: %s" % self.getSuiteDescription(test)) try: - name_override = getattr(test, test._testMethodName).__func__.__dict__[ - "test_case_name" - ] + name_override = _get_method_dict(test)["test_case_name"] except: name_override = None self.case = name_override if name_override else self.case @@ -345,7 +353,11 @@ def startTest(self, test): self.results["suites"][self.suite_number] = { "name": self.suite, "class": test.__class__.__name__, - "module": re.compile(".* \((.*)\)").match(str(test)).group(1), + "module": ( + m.group(1) + if (m := re.compile(r".* \((.*)\)").match(str(test))) + else str(test) + ), "description": self.getSuiteDescription(test), "cases": {}, "used_case_names": {}, @@ -380,34 +392,22 @@ def startTest(self, test): if "test_type" in getattr( test, test._testMethodName ).__func__.__dict__ and set([s.lower() for s in self.test_types]) == set( - [ - s.lower() - for s in getattr(test, test._testMethodName).__func__.__dict__[ - "test_type" - ] - ] + [s.lower() for s in _get_method_dict(test)["test_type"]] ): pass else: - getattr(test, test._testMethodName).__func__.__dict__[ - "__unittest_skip_why__" - ] = 'Test run specified to only run tests of type "%s"' % ",".join( - self.test_types + _get_method_dict(test)["__unittest_skip_why__"] = ( + 'Test run specified to only run tests of type "%s"' + % ",".join(self.test_types) ) - getattr(test, test._testMethodName).__func__.__dict__[ - "__unittest_skip__" - ] = True - if "skip_device" in getattr(test, test._testMethodName).__func__.__dict__: - for device in getattr(test, test._testMethodName).__func__.__dict__[ - "skip_device" - ]: + _get_method_dict(test)["__unittest_skip__"] = True + if "skip_device" in _get_method_dict(test): + for device in _get_method_dict(test)["skip_device"]: if self.config and device.lower() in self.config["device_name"].lower(): - getattr(test, test._testMethodName).__func__.__dict__[ - "__unittest_skip_why__" - ] = "Test is marked to be skipped on %s" % device - getattr(test, test._testMethodName).__func__.__dict__[ - "__unittest_skip__" - ] = True + _get_method_dict(test)["__unittest_skip_why__"] = ( + "Test is marked to be skipped on %s" % device + ) + _get_method_dict(test)["__unittest_skip__"] = True break def stopTest(self, test):