Skip to content

Conversation

@klecki
Copy link
Contributor

@klecki klecki commented Dec 22, 2025

Use nose2 as the only testing framework. Drop nose.

Category: Other

Description:

Remove the WARs used to keep nose alive.

nose2 supports the yield-style test discovery by default @attr has a different filtering syntax (-A) and just checks for presence of truthy test_foo.attribute_name. A decorator uses this mechanism for backward compatibility.

nose2 splits with_setup(setup, teardown) into two separate decorators, a backward compatible decorator is added.

nottest sets special attribute.

SkipTest from unittest is recommended to be used directly (with the same functionality).

Test scripts are adjusted with minimal changes to run through nose2. Followup cleanup can be used for renaming.

Replace unsupported -m regex by attributes

Additional information:

Affected modules and functionalities:

Key points relevant for the review:

Tests:

  • Existing tests apply
  • New tests added
    • Python tests
    • GTests
    • Benchmark
    • Other
  • N/A

Checklist

Documentation

  • Existing documentation applies
  • Documentation updated
    • Docstring
    • Doxygen
    • RST
    • Jupyter
    • Other
  • N/A

DALI team only

Requirements

  • Implements new requirements
  • Affects existing requirements
  • N/A

REQ IDs: N/A

JIRA TASK: N/A

Remove the WARs used to keep nose alive.

nose2 supports the yield-style test discovery by default
@attr has a different filtering syntax (`-A`) and just checks for
presence of truthy test_foo.attribute_name. A decorator uses this
mechanism for backward compatibility.

nose2 splits with_setup(setup, teardown) into two separate decorators,
a backward compatible decorator is added.

nottest sets special attribute.

SkipTest from unittest is recommended to be used directly (with the same
functionality).

Test scripts are adjusted with minimal changes to run through nose2.
Followup cleanup can be used for renaming.

Signed-off-by: Krzysztof Lecki <[email protected]>
@greptile-apps
Copy link

greptile-apps bot commented Dec 22, 2025

Greptile Summary

This PR completes the migration from nose to nose2 as the exclusive testing framework. The changes remove Python 3.12+ compatibility workarounds that were needed for the deprecated nose package.

Key Changes:

  • Removed complex Python 3.12 compatibility hacks (imp module recreation, collections.Callable patches) from nose_utils.py
  • Rewrote nose_utils.py to provide backward-compatible decorators (with_setup, attr, nottest) that wrap nose2 functionality
  • Reimplemented assert_raises and assert_warns using native unittest methods instead of nose.tools
  • Updated 25+ test shell scripts across qa/ directory with nose2 syntax:
    • --attr flag changed to -A for attribute filtering
    • -m regex patterns replaced with -A attribute-based filtering
    • Test names no longer include .py extension
    • Parameterized test syntax changed from :index to .index (e.g., test_name:1test_name.1)
  • Added @attr decorators to Python test files for framework-specific filtering (pytorch, cupy, paddle)
  • Deleted qa/nose_wrapper/__main__.py as it's no longer needed
  • Removed nose from pip_packages, keeping only nose2

Impact:
The migration is comprehensive and affects test discovery, filtering, and execution across the entire test suite. All tests now run exclusively through nose2, simplifying maintenance and improving Python 3.12+ compatibility.

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The migration from nose to nose2 is well-executed and comprehensive. All syntax changes follow nose2 conventions correctly (--attr to -A, .py removal, :index to .index). The backward-compatibility decorators in nose_utils.py properly wrap nose2 functionality. The changes are consistent across all 29 files, and the removal of Python 3.12 workarounds simplifies the codebase. Only minor style improvements suggested.
  • No files require special attention

Important Files Changed

Filename Overview
dali/test/python/nose_utils.py Complete rewrite to use nose2 instead of nose, removing Python 3.12 compatibility workarounds and implementing compatibility decorators
qa/test_template_impl.sh Removed nose wrapper and old nose runner, keeping only nose2 as the test framework
qa/TL0_python-self-test-core/test_body.sh Updated test invocations: changed --attr to -A, .py extension removed, changed : to . for test indices
qa/TL0_tensorflow_plugin/test.sh Updated test invocations to use nose2 syntax, removed .py extensions from test names
qa/TL1_python-self-test_conda/test_body.sh Updated test syntax from : to . for parameterized test selection (test_scans_limit:1 to test_scans_limit.1)

Sequence Diagram

sequenceDiagram
    participant TestScript as Test Script (*.sh)
    participant Nose2 as Nose2 Runner
    participant NoseUtils as nose_utils.py
    participant TestFile as Test Files (*.py)
    participant Unittest as Python unittest

    TestScript->>Nose2: Execute with -A attribute filter
    Note over TestScript,Nose2: Changed from --attr to -A<br/>Changed from -m regex to -A attributes<br/>Removed .py extension from test names
    
    Nose2->>TestFile: Discover tests with @attr decorators
    TestFile->>NoseUtils: Import compatibility decorators
    Note over NoseUtils: Provides backward-compatible<br/>decorators for nose migration:<br/>- with_setup/with_teardown<br/>- attr<br/>- nottest<br/>- assert_raises/assert_warns
    
    NoseUtils->>Unittest: Use unittest assertions
    Note over NoseUtils,Unittest: Direct unittest usage instead<br/>of nose.tools
    
    TestFile->>Nose2: Execute test with setup/teardown
    Nose2->>Unittest: Run assertions
    Unittest-->>Nose2: Return results
    Nose2-->>TestScript: Return test results
Loading

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Comments (1)

  1. dali/test/python/nose_utils.py, line 129-130 (link)

    style: creating a new TestCase instance for each assertion call is unconventional

    Consider creating a module-level instance once:

    Then define tc at module level (after imports) and reuse it in both assert_raises and assert_warns

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

25 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Comments (2)

  1. dali/test/python/test_functional_api.py, line 22 (link)

    logic: This file still imports nose directly and uses nose.tools.eq_ on line 188. Since nose is being removed as a dependency, this will cause an import error.

  2. dali/test/python/test_functional_api.py, line 188 (link)

    logic: Replace nose.tools.eq_ with standard assertion or use assert_equals from nose_utils

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

28 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Signed-off-by: Krzysztof Lecki <[email protected]>
Signed-off-by: Krzysztof Lecki <[email protected]>
Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Comments (1)

  1. dali/test/python/nose_utils.py, line 68 (link)

    syntax: missing self parameter - instance methods must have self as first parameter

29 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@klecki
Copy link
Contributor Author

klecki commented Dec 22, 2025

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [40627092]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [40627092]: BUILD FAILED

Signed-off-by: Krzysztof Lecki <[email protected]>
@klecki
Copy link
Contributor Author

klecki commented Dec 22, 2025

!build

with_teardown as _nose2_with_teardown,
)
from unittest import SkipTest # noqa: F401
import unittest

Check notice

Code scanning / CodeQL

Module is imported with 'import' and 'import from' Note test

Module 'unittest' is imported with both 'import' and 'import from'.
@dali-automaton
Copy link
Collaborator

CI MESSAGE: [40628704]: BUILD STARTED

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Comments (1)

  1. dali/test/python/nose_utils.py, line 83-85 (link)

    style: Consider using the module-level _test_case instance instead of creating a new empty_case() for each assertion:

    This is more efficient and aligns with how assert_raises and assert_warns are implemented.

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

29 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@JanuszL JanuszL self-assigned this Dec 22, 2025
@JanuszL
Copy link
Contributor

JanuszL commented Dec 22, 2025

Do we need to touch unittest_failure.cfg, unittest_slow.cfg or unittest.cfg as well?

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [40628704]: BUILD FAILED

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants