diff --git a/.github/workflows/array-api-intelligent-tests-pr.yml b/.github/workflows/array-api-intelligent-tests-pr.yml deleted file mode 100644 index e67478445676e..0000000000000 --- a/.github/workflows/array-api-intelligent-tests-pr.yml +++ /dev/null @@ -1,85 +0,0 @@ -name: array-api-intelligent-tests-pr -on: - pull_request: - types: [opened, synchronize, reopened, review_requested ] - -permissions: - actions: read - -jobs: - display_test_results: - if: ${{ always() }} - runs-on: ubuntu-latest - needs: - - run_tests - - steps: - - name: Download all test results - uses: actions/download-artifact@v3 - - - name: Combined Test Results - run: | - find . -name "test_results_*.txt" -exec cat {} + > combined_test_results.txt - echo "Test results summary:" - cat combined_test_results.txt - - - name: New Failures Introduced - run: | - find . -name "new_failures_*.txt" -exec cat {} + > combined_failures.txt - if [ -s combined_failures.txt ] - then - echo "This PR introduces the following new failing tests:" - cat combined_failures.txt - else - echo "This PR does not introduce any new test failures! Yippee!" - fi - - run_tests: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - branch: [ 1, 2, 3, 4 ] - - steps: - - name: Checkout Ivy 🛎 - uses: actions/checkout@v3 - with: - path: ivy - persist-credentials: false - submodules: "recursive" - fetch-depth: 100 - - - name: Get Job URL - uses: Tiryoh/gha-jobid-action@v0 - id: jobs - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - job_name: ${{ github.job }} - - - name: Determine and Run Tests - run: | - git clone -b main${{ matrix.branch }} https://github.com/unifyai/Mapping.git --depth 1 - pip install pydriller - cp Mapping/tests.pbz2 ivy/ - cd ivy - python scripts/determine_tests/array_api_determine_tests.py - python scripts/run_tests/array_api_run_tests_pr.py new_failures_${{ matrix.branch }}.txt | tee test_results_${{ matrix.branch }}.txt - cd .. - continue-on-error: true - - - name: Upload test results - uses: actions/upload-artifact@v3 - with: - name: test_results_${{ matrix.branch }} - path: ivy/test_results_${{ matrix.branch }}.txt - - - name: Upload New Failures - uses: actions/upload-artifact@v3 - with: - name: new_failures_${{ matrix.branch }} - path: ivy/new_failures_${{ matrix.branch }}.txt - - - name: Check on failures - if: steps.tests.outcome != 'success' - run: exit 1 diff --git a/.github/workflows/array-api-intelligent-tests.yml b/.github/workflows/array-api-intelligent-tests.yml deleted file mode 100644 index 576bbe9475e16..0000000000000 --- a/.github/workflows/array-api-intelligent-tests.yml +++ /dev/null @@ -1,82 +0,0 @@ -name: array-api-intelligent-tests -on: - workflow_dispatch: - push: - branches: - - 'main' -permissions: - actions: read -jobs: - display_test_results: - if: ${{ always() }} - runs-on: ubuntu-latest - needs: - - run_tests - - steps: - - name: Download all test results - uses: actions/download-artifact@v3 - - - name: Combined Test Results - run: | - find . -name "test_results_*.txt" -exec cat {} + > combined_test_results.txt - echo "Test results summary:" - cat combined_test_results.txt - - run_tests: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - branch: [ 1, 2, 3, 4 ] - - steps: - - name: Checkout Ivy 🛎 - uses: actions/checkout@v3 - with: - path: ivy - persist-credentials: false - submodules: "recursive" - fetch-depth: 100 - - - name: Get Job URL - uses: Tiryoh/gha-jobid-action@v0 - id: jobs - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - job_name: ${{ github.job }} - - - name: Update Mapping and Determine Tests - env: - SSH_DEPLOY_KEY: ${{ secrets.SSH_DEPLOY_KEY }} - run: | - source ./ivy/scripts/shell/clone_mapping.sh main${{ matrix.branch }} - pip install pydriller pymongo - cp Mapping/tests.pbz2 ivy/ - cd ivy - python scripts/determine_tests/array_api_determine_tests.py ${{ matrix.branch }} - cd .. - cp ivy/tests.pbz2 Mapping/ - cd Mapping - git add . - git commit -m "Update Mapping" - git push origin main${{ matrix.branch }} - continue-on-error: true - - - name: Run Tests - id: tests - run: | - cd ivy - set -o pipefail - python scripts/run_tests/array_api_run_tests.py ${{ secrets.REDIS_CONNECTION_URL }} ${{ secrets.REDIS_PASSWORD }} ${{ secrets.MONGODB_PASSWORD }} ${{ github.run_id }} ${{ steps.jobs.outputs.html_url }} | tee test_results_${{ matrix.branch }}.txt - continue-on-error: true - - - name: Upload test results - uses: actions/upload-artifact@v3 - with: - name: test_results_${{ matrix.branch }} - path: ivy/test_results_${{ matrix.branch }}.txt - - - name: Check on failures - if: steps.tests.outcome != 'success' - run: exit 1 diff --git a/.github/workflows/commit-tests.yml b/.github/workflows/commit-tests.yml new file mode 100644 index 0000000000000..f04148dff521a --- /dev/null +++ b/.github/workflows/commit-tests.yml @@ -0,0 +1,56 @@ +name: tests +on: + push: + branches: + - main + pull_request: + branches: + - main + +permissions: + actions: read +jobs: + tests: + runs-on: ubuntu-latest + steps: + - name: Checkout Ivy 🛎 + uses: actions/checkout@v3 + with: + path: ivy + persist-credentials: false + fetch-depth: 100 + + - name: Fetch Commit Changes + id: fetch_changes + run: | + cd ivy + git fetch origin main + git diff origin/main HEAD --output="commit-diff.txt" + + - name: Install ivy and fetch binaries + run: | + cd ivy + sudo pip3 install -e . + mkdir .ivy + touch .ivy/key.pem + echo -n ${{ secrets.USER_API_KEY }} > .ivy/key.pem + cd .. + + - name: Get Job URL + uses: Tiryoh/gha-jobid-action@v0 + id: jobs + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + job_name: ${{ github.job }} + + - name: Run Tests + id: tests + run: | + pip3 install pymongo + cd ivy + docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis unifyai/ivy:latest python3 scripts/run_tests_from_diff.py + continue-on-error: true + + - name: Check on failures + if: steps.tests.outcome != 'success' + run: exit 1 diff --git a/.github/workflows/duplication.yml b/.github/workflows/duplication.yml index 4858881f132ef..2d685f26128bc 100644 --- a/.github/workflows/duplication.yml +++ b/.github/workflows/duplication.yml @@ -1,29 +1,29 @@ -name: duplicate-test-check +name: duplicates on: + push: + branches: + main pull_request: permissions: actions: read jobs: - run-check: - if: contains(github.event.pull_request.labels.*.name, 'Exhaustive CI') || contains(github.event.pull_request.labels.*.name, 'Ivy API Experimental') - runs-on: ubuntu-latest - steps: - - name: Checkout Ivy 🛎 - uses: actions/checkout@v2 - with: - path: ivy - persist-credentials: false - submodules: "recursive" - fetch-depth: 100 + test-duplicates: + runs-on: ubuntu-latest + steps: + - name: Checkout Ivy 🛎 + uses: actions/checkout@v3 + with: + path: ivy + persist-credentials: false + fetch-depth: 100 + - name: Check Duplicate Function + id: tests + run: | + cd ivy + docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis unifyai/ivy:latest python3 scripts/duplicate.py + continue-on-error: true - - name: Check Duplicate Function - id: tests - run: | - cd ivy - docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis unifyai/ivy:latest python3 scripts/duplicate.py - continue-on-error: true - - - name: Check on failures - if: steps.tests.outcome != 'success' - run: exit 1 + - name: Check on failures + if: steps.tests.outcome != 'success' + run: exit 1 diff --git a/.github/workflows/intelligent-tests-pr.yml b/.github/workflows/intelligent-tests-pr.yml deleted file mode 100644 index 91e08239a9d23..0000000000000 --- a/.github/workflows/intelligent-tests-pr.yml +++ /dev/null @@ -1,125 +0,0 @@ -name: intelligent-tests-pr -on: - workflow_dispatch: - pull_request: - types: [opened, synchronize, reopened, review_requested] - -permissions: - actions: read - -jobs: - display_test_results: - if: ${{ always() }} - runs-on: ubuntu-latest - needs: - - run_tests - - steps: - - name: Download all test results - uses: actions/download-artifact@v3 - - - name: Checkout Ivy 🛎 - uses: actions/checkout@v3 - with: - path: ivy - persist-credentials: false - submodules: "recursive" - fetch-depth: 1 - - - name: Combined Test Results - run: | - find . -name "test_results_*.txt" -exec cat {} + > combined_test_results.txt - echo "Test results summary:" - cat combined_test_results.txt - - - name: Label Test Failures - run: | - find . -name "test_failures_*.txt" -exec cat {} + > ivy/combined_failures.txt - pip install pymongo - cd ivy - python3 scripts/run_tests/label_failures.py combined_failures.txt labeled_combined_failures.txt - - - name: Display Test Failures - run: | - cd ivy - if [ -s labeled_combined_failures.txt ] - then - echo "The CI captured the following failing tests based on your changes:" - cat labeled_combined_failures.txt - else - echo "No test failures found based on your changes!" - fi - - run_tests: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - branch: [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, - 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, - 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, - 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, - 121, 122, 123, 124, 125, 126, 127, 128 ] - - steps: - - name: Checkout Ivy 🛎 - uses: actions/checkout@v3 - with: - path: ivy - persist-credentials: false - submodules: "recursive" - fetch-depth: 100 - - - name: Install ivy and fetch binaries - run: | - cd ivy - sudo pip3 install -e . - mkdir .ivy - touch .ivy/key.pem - echo -n ${{ secrets.USER_API_KEY }} > .ivy/key.pem - cd .. - - - name: Get Job URL - uses: Tiryoh/gha-jobid-action@v0 - id: jobs - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - job_name: ${{ github.job }} - - - name: Determine and Run Tests - id: tests - run: | - git clone -b master${{ matrix.branch }} https://github.com/unifyai/Mapping.git --depth 1 - pip install pydriller GitPython - python ivy/scripts/setup_tests/clone-mapping.py - cp Mapping/tests.pbz2 ivy/ - cd ivy - python scripts/determine_tests/determine_tests.py ${{ matrix.branch }} pr - set -o pipefail - python scripts/run_tests/run_tests_pr.py test_failures_${{ matrix.branch }}.txt | tee test_results_${{ matrix.branch }}.txt - cd .. - continue-on-error: true - - - name: Upload test results - uses: actions/upload-artifact@v3 - with: - name: test_results_${{ matrix.branch }} - path: ivy/test_results_${{ matrix.branch }}.txt - - - name: Upload New Failures - uses: actions/upload-artifact@v3 - with: - name: test_failures_${{ matrix.branch }} - path: ivy/test_failures_${{ matrix.branch }}.txt - - - name: Check on failures - if: steps.tests.outcome != 'success' - run: exit 1 diff --git a/.github/workflows/intelligent-tests.yml b/.github/workflows/intelligent-tests.yml deleted file mode 100644 index 23a6e2171d83f..0000000000000 --- a/.github/workflows/intelligent-tests.yml +++ /dev/null @@ -1,103 +0,0 @@ -name: intelligent-tests -on: - workflow_dispatch: - push: - branches: - - 'main' -permissions: - actions: read -jobs: - display_test_results: - if: ${{ always() }} - runs-on: ubuntu-latest - needs: - - run_tests - - steps: - - name: Download all test results - uses: actions/download-artifact@v3 - - - name: Combined Test Results - run: | - find . -name "test_results_*.txt" -exec cat {} + > combined_test_results.txt - echo "Test results summary:" - cat combined_test_results.txt - - run_tests: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - branch: [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, - 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, - 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, - 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, - 121, 122, 123, 124, 125, 126, 127, 128 ] - - steps: - - name: Checkout Ivy 🛎 - uses: actions/checkout@v3 - with: - path: ivy - persist-credentials: false - submodules: "recursive" - fetch-depth: 100 - - - name: Install ivy and fetch binaries - run: | - cd ivy - sudo pip3 install -e . - mkdir .ivy - touch .ivy/key.pem - echo -n ${{ secrets.USER_API_KEY }} > .ivy/key.pem - cd .. - - - name: Get Job URL - uses: Tiryoh/gha-jobid-action@v0 - id: jobs - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - job_name: ${{ github.job }} - - - name: Update Mapping and Determine Tests - env: - SSH_DEPLOY_KEY: ${{ secrets.SSH_DEPLOY_KEY }} - run: | - source ./ivy/scripts/shell/clone_mapping.sh master${{ matrix.branch }} - pip install pydriller pymongo - cp Mapping/tests.pbz2 ivy/ - cd ivy - python scripts/determine_tests/determine_tests.py ${{ matrix.branch }} - cd .. - cp ivy/tests.pbz2 Mapping/ - cd Mapping - git add . - git commit -m "Update Mapping" - git push origin master${{ matrix.branch }} - continue-on-error: true - - - name: Run Tests - id: tests - run: | - cd ivy - set -o pipefail - python scripts/run_tests/run_tests.py ${{ secrets.REDIS_CONNECTION_URL }} ${{ secrets.REDIS_PASSWORD }} ${{ secrets.MONGODB_PASSWORD }} 'false' 'false' ${{ github.run_id }} 'false' 'false' 'false' ${{ steps.jobs.outputs.html_url }} | tee test_results_${{ matrix.branch }}.txt - continue-on-error: true - - - name: Upload test results - uses: actions/upload-artifact@v3 - with: - name: test_results_${{ matrix.branch }} - path: ivy/test_results_${{ matrix.branch }}.txt - - - name: Check on failures - if: steps.tests.outcome != 'success' - run: exit 1 diff --git a/.github/workflows/lint-bot.yml b/.github/workflows/lint-bot.yml deleted file mode 100644 index 52ee85c1ae2d9..0000000000000 --- a/.github/workflows/lint-bot.yml +++ /dev/null @@ -1,16 +0,0 @@ -name: lint-bot - -on: - push: - branches: - - main - workflow_dispatch: - -permissions: - contents: write - -jobs: - fix-linting: - name: Fix Linting - uses: unifyai/workflows/.github/workflows/lint-bot.yml@main - secrets: inherit diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index cfa8c518c2ead..a8b96ced968d0 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -10,7 +10,6 @@ permissions: contents: write jobs: - check-formatting: - name: Check formatting + lint: uses: unifyai/workflows/.github/workflows/lint.yml@main secrets: inherit diff --git a/.github/workflows/manual-tests.yml b/.github/workflows/manual-tests.yml index 6bb0b423712d1..4a4fde57d0c6b 100644 --- a/.github/workflows/manual-tests.yml +++ b/.github/workflows/manual-tests.yml @@ -85,7 +85,6 @@ jobs: with: path: ivy persist-credentials: false - submodules: "recursive" fetch-depth: 100 - name: Install ivy and fetch binaries diff --git a/.github/workflows/test-docstrings.yml b/.github/workflows/test-docstrings.yml index 77be6f4e6c969..ed991f6ec5ad7 100644 --- a/.github/workflows/test-docstrings.yml +++ b/.github/workflows/test-docstrings.yml @@ -1,11 +1,11 @@ name: test-docstrings on: push: - pull_request: - types: [opened, synchronize, reopened, review_requested] + branches: + main workflow_dispatch: jobs: - run-docstring-tests: + docstring-tests: if: ${{(github.event_name == 'push') || contains(github.event.pull_request.labels.*.name, 'Exhaustive CI') || contains(github.event.pull_request.labels.*.name, 'Function Reformatting')}} runs-on: ubuntu-latest steps: @@ -13,7 +13,6 @@ jobs: with: path: ivy persist-credentials: false - submodules: "recursive" - uses: actions/setup-python@v3 with: python-version: "3.8" @@ -21,4 +20,4 @@ jobs: - name: Run Docstring Tests run: | cd ivy - docker run --rm -i -v "$(pwd)":/ivy unifyai/ivy:latest python3 -m pytest ivy_tests/test_docstrings.py + docker run --rm -i -v "$(pwd)":/ivy unifyai/ivy:latest python3 -m pytest ivy_tests/test_docstrings.py -p no:warnings diff --git a/.github/workflows/welcome-message.yml b/.github/workflows/welcome-message.yml index a41cb471ed830..77034baca336a 100644 --- a/.github/workflows/welcome-message.yml +++ b/.github/workflows/welcome-message.yml @@ -4,34 +4,12 @@ on: pull_request_target: types: - opened - - edited - - synchronize - - reopened workflow_call: permissions: pull-requests: write jobs: - pr-compliance-checks: - name: PR Compliance Checks - runs-on: ubuntu-latest - timeout-minutes: 10 - steps: - - uses: mtfoley/pr-compliance-action@v0.5.0 - with: - body-auto-close: false - protected-branch-auto-close: false - body-comment: > - ## Issue Reference - - In order to be considered for merging, the pull request description must refer to a - specific issue number. This is described in our - [contributing guide](https://unify.ai/docs/ivy/overview/contributing/the_basics.html#todo-list-issues) and our PR template. - - This check is looking for a phrase similar to: "Fixes #XYZ" or "Resolves #XYZ" where XYZ is the issue - number that this PR is meant to address. - welcome: name: Welcome runs-on: ubuntu-latest diff --git a/ivy_tests/conftest.py b/ivy_tests/conftest.py index c79160013ec4b..890aab9fa48ec 100644 --- a/ivy_tests/conftest.py +++ b/ivy_tests/conftest.py @@ -66,14 +66,14 @@ def pytest_addoption(parser): "-N", "--num-examples", action="store", - default=25, + default=5, type=int, help="set max examples generated by Hypothesis", ) parser.addoption( "--deadline", action="store", - default=500000, + default=100_000, type=int, help="set deadline for testing one example", ) @@ -151,6 +151,7 @@ def pytest_configure(config): "ivy_profile", **profile_settings, suppress_health_check=(HealthCheck(3), HealthCheck(2), HealthCheck(1)), + phases=[Phase.explicit, Phase.reuse, Phase.generate, Phase.target], print_blob=True, ) diff --git a/scripts/duplicate.py b/scripts/duplicate.py index 589183e308222..dfa9b2dc7d866 100644 --- a/scripts/duplicate.py +++ b/scripts/duplicate.py @@ -1,8 +1,11 @@ +import ast import importlib import os import sys import glob +sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + def get_all_functions_from_directory(root_dir, startswith="test"): if not os.path.exists(root_dir): @@ -22,7 +25,7 @@ def get_all_functions_from_directory(root_dir, startswith="test"): return functions_names -def check_duplicate(): +def check_duplicate_functional_experimental_tests(): fn_test_core = get_all_functions_from_directory( "ivy_tests/test_ivy/test_functional/test_core" ) @@ -34,11 +37,95 @@ def check_duplicate(): ) fn_ivy_test = set(fn_test_core).union(set(fn_test_nn)) common_list = fn_ivy_test.intersection(set(fn_test_experimental)) - return common_list + + # returns True if duplicate found, False if no duplicates found + return len(common_list) > 0 + + +def find_duplicate_functions(root_dir): + """Searches for any duplicate frontend functions within ivy's frontend + api.""" + fns = [] + duplicates = [] + current_class_fns = [] + exclude = [ + # functions to exclude + "dtype", + "device", + "is_leaf", + "ivy_array", + "numel", # torch.Size + "requires_grad", + "symmetrize", + # files to exclude + "base.py", + "func_wrapper.py", + "loss_functions.py", + ] + + # NOTE: Size and Tensor are currently defined in the same file, which + # causes duplication overlapping as the class defs override each + # other when doing the breadth-first ast walk. Not causing any + # problems right now (excluded some methods), but worth noting. + + for root, dirs, files in os.walk(root_dir): + for file in files: + if file.endswith(".py"): + file_path = os.path.join(root, file) + file_name = file_path.split("/")[-1] + if file_name in exclude or file_name.startswith("_"): + continue + with open(file_path, "r") as f: + tree = ast.parse(f.read()) + for node in ast.walk(tree): + if isinstance(node, ast.Module): + current_class = "" + current_class_fns = [] + if not hasattr(node, "col_offset") or node.col_offset == 0: + current_class = "" + current_class_fns = [] + if isinstance(node, ast.ClassDef): + current_class = node.name + current_class_fns = [] + if isinstance(node, ast.FunctionDef): + func_name = node.name + if ( + func_name in exclude # ignore any fns in `exclude` + or func_name.startswith( + "_" + ) # ignore any private or dunder methods + ): + continue + func_path = file_path + full_name = func_path + "::" + func_name + if ( + node.decorator_list + and hasattr(node.decorator_list[0], "id") + and node.decorator_list[0].id == "property" + ): + # ignore properties + continue + if len(current_class) == 0: + if full_name not in fns: + fns.append(full_name) + else: + duplicates.append(full_name) + else: + if full_name not in current_class_fns: + current_class_fns.append(full_name) + else: + duplicates.append(full_name) + return duplicates if __name__ == "__main__": - common_set = check_duplicate() - if len(common_set) != 0: - print("This function already exists in the functional API.") + duplicated_frontends = find_duplicate_functions("ivy/functional/frontends/") + if duplicated_frontends: + print("Duplicate functions found:") + print(duplicated_frontends) + sys.exit(1) + + if check_duplicate_functional_experimental_tests(): sys.exit(1) + + print("No duplicate functions found") diff --git a/scripts/run_tests_from_diff.py b/scripts/run_tests_from_diff.py new file mode 100644 index 0000000000000..52111683cd4a5 --- /dev/null +++ b/scripts/run_tests_from_diff.py @@ -0,0 +1,78 @@ +"""Script that attempts to find the test file(s) corresponding the all the +changes made in a commit (git diff stored in commit-diff.txt), and runs all the +tests it finds.""" + +import os +import re +import subprocess +import sys + + +with open("commit-diff.txt", "r") as f: + diff_lines = f.readlines() + +modified_files = set() +for line in diff_lines: + if line.startswith("diff --git a/"): + file_path = line.split(" ")[2].strip().lstrip("a/") + modified_files.add(file_path) + elif line.startswith("diff --git b/"): + file_path = line.split(" ")[2].strip().lstrip("b/") + modified_files.add(file_path) + elif line.startswith("diff --git "): + file_path = line.split(" ")[2].strip().lstrip("--git ") + modified_files.add(file_path) + +nn = [ + "activations", + "layers", + "losses", + "norms", +] +exclude = [ + "conftest", +] +test_paths = [] + +for file_path in set(modified_files): + suffix = file_path.rsplit("/", 1)[1].replace(".py", "") + + if suffix in exclude: + continue + + # some regex logic to get the correct test file for the given modified file + if "/frontends/" in file_path: + file_path = file_path.replace("/functional", "") + + if "/backends/" in file_path: + file_path = re.sub(r"/backends/.*?/", "/", file_path) + file_path = file_path.rsplit("/", 1)[0] + if suffix in nn: + file_path += f"/nn/{suffix}.py" + else: + file_path += f"/core/{suffix}.py" + + if not file_path.startswith("ivy_tests/"): + path_list = file_path.split("/") + path_list = ["test_" + p for p in path_list] + file_path = "ivy_tests/" + "/".join(path_list) + + # if the test file doesn't exist, step up a directory + # and run those tests instead (if that exists) + if not os.path.exists(file_path): + file_path = file_path.rsplit("/", 1)[0] + + if os.path.exists(file_path) and "ivy_tests/test_ivy/" in file_path: + test_paths.append(file_path) + +print("Running tests:", test_paths) + +for test_path in set(test_paths): + pytest_command = ( + f"pytest {file_path} -p no:warnings --tb=short --backend jax,tensorflow,torch" + ) + print(f"Running test command: {pytest_command}") + result = subprocess.run(pytest_command, shell=True) + + if result.returncode != 0: + sys.exit(result.returncode)