From e845c1e8e0162ef8e59c2727e3076e0e379b5d72 Mon Sep 17 00:00:00 2001 From: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> Date: Wed, 10 Sep 2025 11:50:44 -0700 Subject: [PATCH 01/19] First pass at dispatching test runs Signed-off-by: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> --- .github/workflows/CI.yml | 15 ++-- .github/workflows/run_unit_tests.yml | 100 ++++++++++++++++++--------- .github/workflows/test_package.yml | 25 +++++++ 3 files changed, 101 insertions(+), 39 deletions(-) create mode 100644 .github/workflows/test_package.yml diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 6ce93b0f..1437e5ef 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -21,14 +21,19 @@ jobs: uses: ./.github/workflows/check_package.yml with: package-name: ${{ matrix.package-name }} - run_unit_tests: - name: Run unit tests - uses: ./.github/workflows/run_unit_tests.yml - needs: check_package + test_package: + name: Test ${{ matrix.package-name }} + needs: [get_package_names, check_package] + strategy: + matrix: + package-name: ${{ fromJson(needs.get_package_names.outputs.package-names) }} + uses: ./.github/workflows/test_package.yml + with: + package-name: ${{ matrix.package-name }} report_test_results: name: Report test results uses: ./.github/workflows/report_test_results.yml - needs: run_unit_tests + needs: test_package if: always() permissions: contents: read diff --git a/.github/workflows/run_unit_tests.yml b/.github/workflows/run_unit_tests.yml index 00d34408..f8ba790d 100644 --- a/.github/workflows/run_unit_tests.yml +++ b/.github/workflows/run_unit_tests.yml @@ -2,12 +2,38 @@ name: Run unit tests on: workflow_call: + inputs: + package-name: + description: 'The name of the package folder to check.' + default: '' + required: true + type: string + package-basepath: + description: 'The base path of the package to check, relative to the repo root.' + default: '' + required: true + type: string workflow_dispatch: + inputs: + package-name: + description: 'The name of the package folder to check.' + default: '' + required: true + type: string + package-basepath: + description: 'The base path of the package to check, relative to the repo root.' + default: '' + required: true + type: string jobs: run_unit_tests: - name: Run unit tests + name: Run unit tests for ${{ inputs.package-name }} runs-on: ${{ matrix.os }} + defaults: + run: + # Set the working-directory for all steps in this job. + working-directory: ${{ github.workspace }}/${{ inputs.package-basepath }}/${{ inputs.package-name }} strategy: matrix: os: [windows-latest, ubuntu-latest] @@ -27,38 +53,44 @@ jobs: python-version: ${{ matrix.python-version }} - name: Set up Poetry uses: ni/python-actions/setup-poetry@f0276f7f58868ec0d0d1a86377287c9e6fe0c6e7 # v0.5.0 - - name: Run and upload unit tests - ni.protobuf.types + - name: Run and upload unit tests for ${{ inputs.package-name }} uses: ./.github/actions/run_and_upload_unit_tests with: - package-name: ni.protobuf.types - - name: Run and upload unit tests - ni.panels.v1.proto - uses: ./.github/actions/run_and_upload_unit_tests - with: - package-name: ni.panels.v1.proto - - name: Run and upload unit tests - ni.measurementlink.measurement.v1.proto - uses: ./.github/actions/run_and_upload_unit_tests - with: - package-name: ni.measurementlink.measurement.v1.proto - - name: Run and upload unit tests - ni.measurementlink.measurement.v2.proto - uses: ./.github/actions/run_and_upload_unit_tests - with: - package-name: ni.measurementlink.measurement.v2.proto - - name: Run and upload unit tests - ni-grpc-extensions - uses: ./.github/actions/run_and_upload_unit_tests - with: - package-name: ni-grpc-extensions - - name: Run and upload unit tests - ni.measurementlink.discovery.v1.client - uses: ./.github/actions/run_and_upload_unit_tests - with: - package-name: ni.measurementlink.discovery.v1.client - - name: Run and upload unit tests - ni.measurementlink.pinmap.v1.client - uses: ./.github/actions/run_and_upload_unit_tests - with: - package-name: ni.measurementlink.pinmap.v1.client - # Run grpc_generator unit tests on its oldest supported version. - - name: Run and upload unit tests - grpc_generator - if: ${{ !contains(fromJSON('["3.9", "3.10"]'), matrix.python-version) }} - uses: ./.github/actions/run_and_upload_unit_tests - with: - package-name: grpc_generator - package-basepath: tools + package-name: ${{ inputs.package-name }} + package-basepath: ${{ inputs.package-basepath }} + + # - name: Run and upload unit tests - ni.protobuf.types + # uses: ./.github/actions/run_and_upload_unit_tests + # with: + # package-name: ni.protobuf.types + # - name: Run and upload unit tests - ni.panels.v1.proto + # uses: ./.github/actions/run_and_upload_unit_tests + # with: + # package-name: ni.panels.v1.proto + # - name: Run and upload unit tests - ni.measurementlink.measurement.v1.proto + # uses: ./.github/actions/run_and_upload_unit_tests + # with: + # package-name: ni.measurementlink.measurement.v1.proto + # - name: Run and upload unit tests - ni.measurementlink.measurement.v2.proto + # uses: ./.github/actions/run_and_upload_unit_tests + # with: + # package-name: ni.measurementlink.measurement.v2.proto + # - name: Run and upload unit tests - ni-grpc-extensions + # uses: ./.github/actions/run_and_upload_unit_tests + # with: + # package-name: ni-grpc-extensions + # - name: Run and upload unit tests - ni.measurementlink.discovery.v1.client + # uses: ./.github/actions/run_and_upload_unit_tests + # with: + # package-name: ni.measurementlink.discovery.v1.client + # - name: Run and upload unit tests - ni.measurementlink.pinmap.v1.client + # uses: ./.github/actions/run_and_upload_unit_tests + # with: + # package-name: ni.measurementlink.pinmap.v1.client + # # Run grpc_generator unit tests on its oldest supported version. + # - name: Run and upload unit tests - grpc_generator + # if: ${{ !contains(fromJSON('["3.9", "3.10"]'), matrix.python-version) }} + # uses: ./.github/actions/run_and_upload_unit_tests + # with: + # package-name: grpc_generator + # package-basepath: tools diff --git a/.github/workflows/test_package.yml b/.github/workflows/test_package.yml new file mode 100644 index 00000000..e6dd56bb --- /dev/null +++ b/.github/workflows/test_package.yml @@ -0,0 +1,25 @@ +name: Test package + +on: + workflow_call: + inputs: + package-name: + description: 'The name of the package folder to test.' + default: '' + required: true + type: string + +jobs: + get_package_info: + name: Get package info for ${{ inputs.package-name }} + uses: ./.github/workflows/get_package_info.yml + with: + package-name: ${{ inputs.package-name }} + run_unit_tests: + if: ${{ needs.get_package_info.outputs.should-run-tests == 'true' }} + name: Run unit tests for ${{ inputs.package-name }} + needs: get_package_info + uses: ./.github/workflows/run_unit_tests.yml + with: + package-name: ${{ inputs.package-name }} + package-basepath: ${{ needs.get_package_info.outputs.package-basepath }} From 87a33d954d6eebaf18d521b4708973fbd89448a1 Mon Sep 17 00:00:00 2001 From: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> Date: Wed, 10 Sep 2025 12:17:17 -0700 Subject: [PATCH 02/19] Move python matrix up one level Signed-off-by: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> --- .github/workflows/run_unit_tests.yml | 16 +++++++++++++--- .github/workflows/test_package.yml | 6 +++++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/.github/workflows/run_unit_tests.yml b/.github/workflows/run_unit_tests.yml index f8ba790d..8b97f604 100644 --- a/.github/workflows/run_unit_tests.yml +++ b/.github/workflows/run_unit_tests.yml @@ -13,6 +13,11 @@ on: default: '' required: true type: string + python-version: + description: 'The version of Python to use' + default: 3.11.9 + required: true + type: string workflow_dispatch: inputs: package-name: @@ -25,10 +30,15 @@ on: default: '' required: true type: string + python-version: + description: 'The version of Python to use' + default: 3.11.9 + required: true + type: string jobs: run_unit_tests: - name: Run unit tests for ${{ inputs.package-name }} + name: Run unit tests for ${{ inputs.package-name }} on ${{ matrix.os }} runs-on: ${{ matrix.os }} defaults: run: @@ -37,7 +47,7 @@ jobs: strategy: matrix: os: [windows-latest, ubuntu-latest] - python-version: [3.9, '3.10', 3.11, 3.12, 3.13] + # python-version: [3.9, '3.10', 3.11, 3.12, 3.13] # Fail-fast skews the pass/fail ratio and seems to make pytest produce # incomplete JUnit XML results. fail-fast: false @@ -50,7 +60,7 @@ jobs: uses: ni/python-actions/setup-python@f0276f7f58868ec0d0d1a86377287c9e6fe0c6e7 # v0.5.0 id: setup-python with: - python-version: ${{ matrix.python-version }} + python-version: ${{ inputs.python-version }} - name: Set up Poetry uses: ni/python-actions/setup-poetry@f0276f7f58868ec0d0d1a86377287c9e6fe0c6e7 # v0.5.0 - name: Run and upload unit tests for ${{ inputs.package-name }} diff --git a/.github/workflows/test_package.yml b/.github/workflows/test_package.yml index e6dd56bb..cdcb3734 100644 --- a/.github/workflows/test_package.yml +++ b/.github/workflows/test_package.yml @@ -17,9 +17,13 @@ jobs: package-name: ${{ inputs.package-name }} run_unit_tests: if: ${{ needs.get_package_info.outputs.should-run-tests == 'true' }} - name: Run unit tests for ${{ inputs.package-name }} + strategy: + matrix: + python-version: [3.9, '3.10', 3.11, 3.12, 3.13] + name: Run unit tests for ${{ inputs.package-name }} with ${{ matrix.python-version }} needs: get_package_info uses: ./.github/workflows/run_unit_tests.yml with: package-name: ${{ inputs.package-name }} package-basepath: ${{ needs.get_package_info.outputs.package-basepath }} + python-version: ${{ matrix.python-version }} From a5b732efe91ad3041cc7556fda6f72f3b387aa7e Mon Sep 17 00:00:00 2001 From: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> Date: Wed, 10 Sep 2025 12:50:41 -0700 Subject: [PATCH 03/19] Prevent name collisions by passing python version - the matrix value is not longer available because it is too far up the call tree Signed-off-by: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> --- .github/actions/run_and_upload_unit_tests/action.yml | 7 +++++-- .github/workflows/run_unit_tests.yml | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/actions/run_and_upload_unit_tests/action.yml b/.github/actions/run_and_upload_unit_tests/action.yml index d72df749..04789edc 100644 --- a/.github/actions/run_and_upload_unit_tests/action.yml +++ b/.github/actions/run_and_upload_unit_tests/action.yml @@ -8,6 +8,9 @@ inputs: description: 'Relative path to the parent directory of the package.' required: false default: 'packages' + python-version: + description: 'The version of Python to use' + required: true runs: using: "composite" steps: @@ -21,12 +24,12 @@ runs: working-directory: ${{ github.workspace }}/${{ inputs.package-basepath }}/${{ inputs.package-name }} shell: bash - name: Run ${{ inputs.package-name }} unit tests and code coverage - run: poetry run pytest ./tests/unit -v --cov=${{ inputs.package-name }} --junitxml=test_results/${{ inputs.package-name }}-${{ matrix.os }}-py${{ matrix.python-version }}.xml + run: poetry run pytest ./tests/unit -v --cov=${{ inputs.package-name }} --junitxml=test_results/${{ inputs.package-name }}-${{ matrix.os }}-py${{ inputs.python-version }}.xml working-directory: ${{ github.workspace }}/${{ inputs.package-basepath }}/${{ inputs.package-name }} shell: bash - name: Upload ${{ inputs.package-name }} test results uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: - name: test_results_unit_${{ inputs.package-name }}_${{ matrix.os }}_py${{ matrix.python-version }} + name: test_results_unit_${{ inputs.package-name }}_${{ matrix.os }}_py${{ inputs.python-version }} path: ${{ github.workspace }}/${{ inputs.package-basepath }}/${{ inputs.package-name }}/test_results/*.xml if: always() diff --git a/.github/workflows/run_unit_tests.yml b/.github/workflows/run_unit_tests.yml index 8b97f604..db114094 100644 --- a/.github/workflows/run_unit_tests.yml +++ b/.github/workflows/run_unit_tests.yml @@ -68,6 +68,7 @@ jobs: with: package-name: ${{ inputs.package-name }} package-basepath: ${{ inputs.package-basepath }} + python-version: ${{ inputs.python-version }} # - name: Run and upload unit tests - ni.protobuf.types # uses: ./.github/actions/run_and_upload_unit_tests From d1e5b1cfd3fa6d587eaa93a758bcc462550267ef Mon Sep 17 00:00:00 2001 From: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> Date: Wed, 10 Sep 2025 13:05:12 -0700 Subject: [PATCH 04/19] Move os matrix to match python location Signed-off-by: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> --- .../actions/run_and_upload_unit_tests/action.yml | 7 +++++-- .github/workflows/run_unit_tests.yml | 13 +++++++++++-- .github/workflows/test_package.yml | 2 ++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/.github/actions/run_and_upload_unit_tests/action.yml b/.github/actions/run_and_upload_unit_tests/action.yml index 04789edc..6574d00b 100644 --- a/.github/actions/run_and_upload_unit_tests/action.yml +++ b/.github/actions/run_and_upload_unit_tests/action.yml @@ -11,6 +11,9 @@ inputs: python-version: description: 'The version of Python to use' required: true + os: + description: 'The name of the OS to use' + required: true runs: using: "composite" steps: @@ -24,12 +27,12 @@ runs: working-directory: ${{ github.workspace }}/${{ inputs.package-basepath }}/${{ inputs.package-name }} shell: bash - name: Run ${{ inputs.package-name }} unit tests and code coverage - run: poetry run pytest ./tests/unit -v --cov=${{ inputs.package-name }} --junitxml=test_results/${{ inputs.package-name }}-${{ matrix.os }}-py${{ inputs.python-version }}.xml + run: poetry run pytest ./tests/unit -v --cov=${{ inputs.package-name }} --junitxml=test_results/${{ inputs.package-name }}-${{ inputs.os }}-py${{ inputs.python-version }}.xml working-directory: ${{ github.workspace }}/${{ inputs.package-basepath }}/${{ inputs.package-name }} shell: bash - name: Upload ${{ inputs.package-name }} test results uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: - name: test_results_unit_${{ inputs.package-name }}_${{ matrix.os }}_py${{ inputs.python-version }} + name: test_results_unit_${{ inputs.package-name }}_${{ inputs.os }}_py${{ inputs.python-version }} path: ${{ github.workspace }}/${{ inputs.package-basepath }}/${{ inputs.package-name }}/test_results/*.xml if: always() diff --git a/.github/workflows/run_unit_tests.yml b/.github/workflows/run_unit_tests.yml index db114094..24065e16 100644 --- a/.github/workflows/run_unit_tests.yml +++ b/.github/workflows/run_unit_tests.yml @@ -18,6 +18,10 @@ on: default: 3.11.9 required: true type: string + os: + description: 'The name of the OS to use' + required: true + type: string workflow_dispatch: inputs: package-name: @@ -35,6 +39,10 @@ on: default: 3.11.9 required: true type: string + os: + description: 'The name of the OS to use' + required: true + type: string jobs: run_unit_tests: @@ -45,8 +53,8 @@ jobs: # Set the working-directory for all steps in this job. working-directory: ${{ github.workspace }}/${{ inputs.package-basepath }}/${{ inputs.package-name }} strategy: - matrix: - os: [windows-latest, ubuntu-latest] + # matrix: + # os: [windows-latest, ubuntu-latest] # python-version: [3.9, '3.10', 3.11, 3.12, 3.13] # Fail-fast skews the pass/fail ratio and seems to make pytest produce # incomplete JUnit XML results. @@ -69,6 +77,7 @@ jobs: package-name: ${{ inputs.package-name }} package-basepath: ${{ inputs.package-basepath }} python-version: ${{ inputs.python-version }} + os: ${{ inputs.os }} # - name: Run and upload unit tests - ni.protobuf.types # uses: ./.github/actions/run_and_upload_unit_tests diff --git a/.github/workflows/test_package.yml b/.github/workflows/test_package.yml index cdcb3734..442e2fea 100644 --- a/.github/workflows/test_package.yml +++ b/.github/workflows/test_package.yml @@ -19,6 +19,7 @@ jobs: if: ${{ needs.get_package_info.outputs.should-run-tests == 'true' }} strategy: matrix: + os: [windows-latest, ubuntu-latest] python-version: [3.9, '3.10', 3.11, 3.12, 3.13] name: Run unit tests for ${{ inputs.package-name }} with ${{ matrix.python-version }} needs: get_package_info @@ -27,3 +28,4 @@ jobs: package-name: ${{ inputs.package-name }} package-basepath: ${{ needs.get_package_info.outputs.package-basepath }} python-version: ${{ matrix.python-version }} + os: ${{ matrix.os }} From dc8f39e39609adc714e46ff35fbf7bef1c2e4510 Mon Sep 17 00:00:00 2001 From: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> Date: Wed, 10 Sep 2025 13:15:12 -0700 Subject: [PATCH 05/19] Fix run_unit_tests variable usage Signed-off-by: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> --- .github/workflows/run_unit_tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/run_unit_tests.yml b/.github/workflows/run_unit_tests.yml index 24065e16..bbaaa553 100644 --- a/.github/workflows/run_unit_tests.yml +++ b/.github/workflows/run_unit_tests.yml @@ -46,8 +46,8 @@ on: jobs: run_unit_tests: - name: Run unit tests for ${{ inputs.package-name }} on ${{ matrix.os }} - runs-on: ${{ matrix.os }} + name: Run unit tests for ${{ inputs.package-name }} on ${{ inputs.os }} + runs-on: ${{ inputs.os }} defaults: run: # Set the working-directory for all steps in this job. From f1391796c9bfb2e8fd8d89565d05421fda8bfce1 Mon Sep 17 00:00:00 2001 From: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> Date: Wed, 10 Sep 2025 13:30:00 -0700 Subject: [PATCH 06/19] Let grpc_generator use all supported Python versions Signed-off-by: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> --- tools/grpc_generator/poetry.lock | 175 ++++++++++++++++++++++++++-- tools/grpc_generator/pyproject.toml | 7 +- 2 files changed, 169 insertions(+), 13 deletions(-) diff --git a/tools/grpc_generator/poetry.lock b/tools/grpc_generator/poetry.lock index 50d7aa18..dec7c403 100644 --- a/tools/grpc_generator/poetry.lock +++ b/tools/grpc_generator/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.4 and should not be changed by hand. [[package]] name = "bandit" @@ -6,6 +6,7 @@ version = "1.8.6" description = "Security oriented static analyser for python code." optional = false python-versions = ">=3.9" +groups = ["lint"] files = [ {file = "bandit-1.8.6-py3-none-any.whl", hash = "sha256:3348e934d736fcdb68b6aa4030487097e23a501adf3e7827b63658df464dddd0"}, {file = "bandit-1.8.6.tar.gz", hash = "sha256:dbfe9c25fc6961c2078593de55fd19f2559f9e45b99f1272341f5b95dea4e56b"}, @@ -16,12 +17,13 @@ colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""} PyYAML = ">=5.3.1" rich = "*" stevedore = ">=1.20.0" +tomli = {version = ">=1.1.0", optional = true, markers = "python_version < \"3.11\" and extra == \"toml\""} [package.extras] baseline = ["GitPython (>=3.1.30)"] sarif = ["jschema-to-python (>=1.2.3)", "sarif-om (>=1.0.4)"] test = ["beautifulsoup4 (>=4.8.0)", "coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "pylint (==1.9.4)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)"] -toml = ["tomli (>=1.1.0)"] +toml = ["tomli (>=1.1.0) ; python_version < \"3.11\""] yaml = ["PyYAML"] [[package]] @@ -30,6 +32,7 @@ version = "25.1.0" description = "The uncompromising code formatter." optional = false python-versions = ">=3.9" +groups = ["lint"] files = [ {file = "black-25.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:759e7ec1e050a15f89b770cefbf91ebee8917aac5c20483bc2d80a6c3a04df32"}, {file = "black-25.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e519ecf93120f34243e6b0054db49c00a35f84f195d5bce7e9f5cfc578fc2da"}, @@ -61,6 +64,8 @@ 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)"] @@ -68,12 +73,30 @@ d = ["aiohttp (>=3.10)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] +[[package]] +name = "click" +version = "8.1.8" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.7" +groups = ["main", "lint"] +markers = "python_version == \"3.9\"" +files = [ + {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, + {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + [[package]] name = "click" version = "8.2.1" description = "Composable command line interface toolkit" optional = false python-versions = ">=3.10" +groups = ["main", "lint"] +markers = "python_version >= \"3.10\"" files = [ {file = "click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b"}, {file = "click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202"}, @@ -88,10 +111,12 @@ version = "0.4.6" description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["main", "lint", "test"] files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +markers = {main = "platform_system == \"Windows\"", lint = "platform_system == \"Windows\"", test = "sys_platform == \"win32\""} [[package]] name = "coverage" @@ -99,6 +124,7 @@ version = "7.10.1" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.9" +groups = ["test"] files = [ {file = "coverage-7.10.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1c86eb388bbd609d15560e7cc0eb936c102b6f43f31cf3e58b4fd9afe28e1372"}, {file = "coverage-7.10.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6b4ba0f488c1bdb6bd9ba81da50715a372119785458831c73428a8566253b86b"}, @@ -190,8 +216,30 @@ files = [ {file = "coverage-7.10.1.tar.gz", hash = "sha256:ae2b4856f29ddfe827106794f3589949a57da6f0d38ab01e24ec35107979ba57"}, ] +[package.dependencies] +tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} + [package.extras] -toml = ["tomli"] +toml = ["tomli ; python_full_version <= \"3.11.0a6\""] + +[[package]] +name = "exceptiongroup" +version = "1.3.0" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +groups = ["test"] +markers = "python_version < \"3.11\"" +files = [ + {file = "exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10"}, + {file = "exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88"}, +] + +[package.dependencies] +typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.13\""} + +[package.extras] +test = ["pytest (>=6)"] [[package]] name = "flake8" @@ -199,6 +247,8 @@ version = "5.0.4" description = "the modular source code checker: pep8 pyflakes and co" optional = false python-versions = ">=3.6.1" +groups = ["lint"] +markers = "python_version < \"3.12\"" files = [ {file = "flake8-5.0.4-py2.py3-none-any.whl", hash = "sha256:7a1cf6b73744f5806ab95e526f6f0d8c01c66d7bbe349562d22dfca20610b248"}, {file = "flake8-5.0.4.tar.gz", hash = "sha256:6fbe320aad8d6b95cec8b8e47bc933004678dc63095be98528b7bdd2a9f510db"}, @@ -215,6 +265,8 @@ version = "6.1.0" description = "the modular source code checker: pep8 pyflakes and co" optional = false python-versions = ">=3.8.1" +groups = ["lint"] +markers = "python_version >= \"3.12\"" files = [ {file = "flake8-6.1.0-py2.py3-none-any.whl", hash = "sha256:ffdfce58ea94c6580c77888a86506937f9a1a227dfcd15f245d694ae20a6b6e5"}, {file = "flake8-6.1.0.tar.gz", hash = "sha256:d5b3857f07c030bdb5bf41c7f53799571d75c4491748a3adcd47de929e34cd23"}, @@ -231,6 +283,7 @@ version = "0.3.6" description = "flake8 plugin to call black as a code style validator" optional = false python-versions = ">=3.7" +groups = ["lint"] files = [ {file = "flake8-black-0.3.6.tar.gz", hash = "sha256:0dfbca3274777792a5bcb2af887a4cad72c72d0e86c94e08e3a3de151bb41c34"}, {file = "flake8_black-0.3.6-py3-none-any.whl", hash = "sha256:fe8ea2eca98d8a504f22040d9117347f6b367458366952862ac3586e7d4eeaca"}, @@ -239,6 +292,7 @@ files = [ [package.dependencies] black = ">=22.1.0" flake8 = ">=3" +tomli = {version = "*", markers = "python_version < \"3.11\""} [package.extras] develop = ["build", "twine"] @@ -249,6 +303,7 @@ version = "1.7.0" description = "Extension for flake8 which uses pydocstyle to check docstrings" optional = false python-versions = ">=3.7" +groups = ["lint"] files = [ {file = "flake8_docstrings-1.7.0-py2.py3-none-any.whl", hash = "sha256:51f2344026da083fc084166a9353f5082b01f72901df422f74b4d953ae88ac75"}, {file = "flake8_docstrings-1.7.0.tar.gz", hash = "sha256:4c8cc748dc16e6869728699e5d0d685da9a10b0ea718e090b1ba088e67a941af"}, @@ -264,6 +319,7 @@ version = "0.18.2" description = "Flake8 and pylama plugin that checks the ordering of import statements." optional = false python-versions = "*" +groups = ["lint"] files = [ {file = "flake8-import-order-0.18.2.tar.gz", hash = "sha256:e23941f892da3e0c09d711babbb0c73bc735242e9b216b726616758a920d900e"}, {file = "flake8_import_order-0.18.2-py2.py3-none-any.whl", hash = "sha256:82ed59f1083b629b030ee9d3928d9e06b6213eb196fe745b3a7d4af2168130df"}, @@ -279,6 +335,7 @@ version = "1.74.0" description = "HTTP/2-based RPC framework" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "grpcio-1.74.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:85bd5cdf4ed7b2d6438871adf6afff9af7096486fcf51818a81b77ef4dd30907"}, {file = "grpcio-1.74.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:68c8ebcca945efff9d86d8d6d7bfb0841cf0071024417e2d7f45c5e46b5b08eb"}, @@ -342,6 +399,8 @@ version = "1.49.1" description = "Protobuf code generator for gRPC" optional = false python-versions = ">=3.7" +groups = ["main"] +markers = "python_version < \"3.12\"" files = [ {file = "grpcio-tools-1.49.1.tar.gz", hash = "sha256:84cc64e5b46bad43d5d7bd2fd772b656eba0366961187a847e908e2cb735db91"}, {file = "grpcio_tools-1.49.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:2dfb6c7ece84d46bd690b23d3e060d18115c8bc5047d2e8a33e6747ed323a348"}, @@ -401,6 +460,8 @@ version = "1.59.0" description = "Protobuf code generator for gRPC" optional = false python-versions = ">=3.7" +groups = ["main"] +markers = "python_version == \"3.12\"" files = [ {file = "grpcio-tools-1.59.0.tar.gz", hash = "sha256:aa4018f2d8662ac4d9830445d3d253a11b3e096e8afe20865547137aa1160e93"}, {file = "grpcio_tools-1.59.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:882b809b42b5464bee55288f4e60837297f9618e53e69ae3eea6d61b05ce48fa"}, @@ -469,6 +530,8 @@ version = "1.67.0" description = "Protobuf code generator for gRPC" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version >= \"3.13\"" files = [ {file = "grpcio_tools-1.67.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:12aa38af76b5ef00a55808c7c374ed18d5dc7cc8081b717e56da3c50df1776e2"}, {file = "grpcio_tools-1.67.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:b0b03d055127bbc7c629454804b53b5cad2cedfcf904576d159a8a04c22b8e66"}, @@ -538,6 +601,7 @@ version = "2.1.0" description = "brain-dead simple config-ini parsing" optional = false python-versions = ">=3.8" +groups = ["test"] files = [ {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, @@ -549,6 +613,7 @@ version = "6.0.1" description = "A Python utility / library to sort Python imports." optional = false python-versions = ">=3.9.0" +groups = ["lint"] files = [ {file = "isort-6.0.1-py3-none-any.whl", hash = "sha256:2dc5d7f65c9678d94c88dfc29161a320eec67328bc97aad576874cb4be1e9615"}, {file = "isort-6.0.1.tar.gz", hash = "sha256:1cb5df28dfbc742e490c5e41bad6da41b805b0a8be7bc93cd0fb2a8a890ac450"}, @@ -564,6 +629,7 @@ version = "3.0.0" description = "Python port of markdown-it. Markdown parsing, done right!" optional = false python-versions = ">=3.8" +groups = ["lint"] files = [ {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, @@ -588,6 +654,7 @@ version = "0.7.0" description = "McCabe checker, plugin for flake8" optional = false python-versions = ">=3.6" +groups = ["lint"] files = [ {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, @@ -599,6 +666,7 @@ version = "0.1.2" description = "Markdown URL utilities" optional = false python-versions = ">=3.7" +groups = ["lint"] files = [ {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, @@ -610,6 +678,7 @@ version = "1.17.1" description = "Optional static typing for Python" optional = false python-versions = ">=3.9" +groups = ["lint"] files = [ {file = "mypy-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3fbe6d5555bf608c47203baa3e72dbc6ec9965b3d7c318aa9a4ca76f465bd972"}, {file = "mypy-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:80ef5c058b7bce08c83cac668158cb7edea692e458d21098c7d3bce35a5d43e7"}, @@ -654,6 +723,7 @@ files = [ [package.dependencies] mypy_extensions = ">=1.0.0" pathspec = ">=0.9.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} typing_extensions = ">=4.6.0" [package.extras] @@ -669,6 +739,7 @@ version = "1.1.0" description = "Type system extensions for programs checked with the mypy type checker." optional = false python-versions = ">=3.8" +groups = ["lint"] files = [ {file = "mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505"}, {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, @@ -680,6 +751,7 @@ version = "3.6.0" description = "Generate mypy stub files from protobuf specs" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "mypy-protobuf-3.6.0.tar.gz", hash = "sha256:02f242eb3409f66889f2b1a3aa58356ec4d909cdd0f93115622e9e70366eca3c"}, {file = "mypy_protobuf-3.6.0-py3-none-any.whl", hash = "sha256:56176e4d569070e7350ea620262478b49b7efceba4103d468448f1d21492fd6c"}, @@ -695,6 +767,7 @@ version = "0.4.7" description = "NI's internal and external Python linter rules and plugins" optional = false python-versions = "<4.0,>=3.7" +groups = ["lint"] files = [ {file = "ni_python_styleguide-0.4.7-py3-none-any.whl", hash = "sha256:4b1ae36315a53d1ef0f996cf868cfca997e3a80b431808e46c632467eacd2d09"}, {file = "ni_python_styleguide-0.4.7.tar.gz", hash = "sha256:b510bb6974bdb907d0d10f14e985e90304d5f02590f5bafab333ebbaa663ef81"}, @@ -725,6 +798,7 @@ version = "1.9.1" description = "Node.js virtual environment builder" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["lint"] files = [ {file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"}, {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"}, @@ -736,6 +810,7 @@ version = "22.17.1" description = "unoffical Node.js package" optional = false python-versions = ">=3.7" +groups = ["lint"] files = [ {file = "nodejs_wheel_binaries-22.17.1-py2.py3-none-macosx_11_0_arm64.whl", hash = "sha256:1f4d208c0c087a2909b6e9e6e0735da083dc997aa74e9b302703b0798b2faa4c"}, {file = "nodejs_wheel_binaries-22.17.1-py2.py3-none-macosx_11_0_x86_64.whl", hash = "sha256:457ada98c6e3e03c7fd3f7d6a55572b70af7155c8dd908246373c63697226db6"}, @@ -754,6 +829,7 @@ version = "25.0" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" +groups = ["lint", "test"] files = [ {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, @@ -765,6 +841,7 @@ version = "0.12.1" description = "Utility library for gitignore style pattern matching of file paths." optional = false python-versions = ">=3.8" +groups = ["lint"] files = [ {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, @@ -776,6 +853,7 @@ version = "6.1.1" description = "Python Build Reasonableness" optional = false python-versions = ">=2.6" +groups = ["lint"] files = [ {file = "pbr-6.1.1-py2.py3-none-any.whl", hash = "sha256:38d4daea5d9fa63b3f626131b9d34947fd0c8be9b05a29276870580050a25a76"}, {file = "pbr-6.1.1.tar.gz", hash = "sha256:93ea72ce6989eb2eed99d0f75721474f69ad88128afdef5ac377eb797c4bf76b"}, @@ -790,6 +868,7 @@ version = "0.15.1" description = "Check PEP-8 naming conventions, plugin for flake8" optional = false python-versions = ">=3.9" +groups = ["lint"] files = [ {file = "pep8_naming-0.15.1-py3-none-any.whl", hash = "sha256:eb63925e7fd9e028c7f7ee7b1e413ec03d1ee5de0e627012102ee0222c273c86"}, {file = "pep8_naming-0.15.1.tar.gz", hash = "sha256:f6f4a499aba2deeda93c1f26ccc02f3da32b035c8b2db9696b730ef2c9639d29"}, @@ -804,6 +883,7 @@ version = "4.3.8" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.9" +groups = ["lint"] files = [ {file = "platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4"}, {file = "platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc"}, @@ -820,6 +900,7 @@ version = "1.6.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.9" +groups = ["test"] files = [ {file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"}, {file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"}, @@ -835,6 +916,8 @@ version = "4.25.8" description = "" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version <= \"3.12\"" files = [ {file = "protobuf-4.25.8-cp310-abi3-win32.whl", hash = "sha256:504435d831565f7cfac9f0714440028907f1975e4bed228e58e72ecfff58a1e0"}, {file = "protobuf-4.25.8-cp310-abi3-win_amd64.whl", hash = "sha256:bd551eb1fe1d7e92c1af1d75bdfa572eff1ab0e5bf1736716814cdccdb2360f9"}, @@ -855,6 +938,8 @@ version = "5.29.5" description = "" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version >= \"3.13\"" files = [ {file = "protobuf-5.29.5-cp310-abi3-win32.whl", hash = "sha256:3f1c6468a2cfd102ff4703976138844f78ebd1fb45f49011afc5139e9e283079"}, {file = "protobuf-5.29.5-cp310-abi3-win_amd64.whl", hash = "sha256:3f76e3a3675b4a4d867b52e4a5f5b78a2ef9565549d4037e06cf7b0942b1d3fc"}, @@ -875,6 +960,8 @@ version = "2.9.1" description = "Python style guide checker" optional = false python-versions = ">=3.6" +groups = ["lint"] +markers = "python_version < \"3.12\"" files = [ {file = "pycodestyle-2.9.1-py2.py3-none-any.whl", hash = "sha256:d1735fc58b418fd7c5f658d28d943854f8a849b01a5d0a1e6f3f3fdd0166804b"}, {file = "pycodestyle-2.9.1.tar.gz", hash = "sha256:2c9607871d58c76354b697b42f5d57e1ada7d261c261efac224b664affdc5785"}, @@ -886,6 +973,8 @@ version = "2.11.1" description = "Python style guide checker" optional = false python-versions = ">=3.8" +groups = ["lint"] +markers = "python_version >= \"3.12\"" files = [ {file = "pycodestyle-2.11.1-py2.py3-none-any.whl", hash = "sha256:44fe31000b2d866f2e41841b18528a505fbd7fef9017b04eff4e2648a0fadc67"}, {file = "pycodestyle-2.11.1.tar.gz", hash = "sha256:41ba0e7afc9752dfb53ced5489e89f8186be00e599e712660695b7a75ff2663f"}, @@ -897,6 +986,7 @@ version = "6.3.0" description = "Python docstring style checker" optional = false python-versions = ">=3.6" +groups = ["lint"] files = [ {file = "pydocstyle-6.3.0-py3-none-any.whl", hash = "sha256:118762d452a49d6b05e194ef344a55822987a462831ade91ec5c06fd2169d019"}, {file = "pydocstyle-6.3.0.tar.gz", hash = "sha256:7ce43f0c0ac87b07494eb9c0b462c0b73e6ff276807f204d6b53edc72b7e44e1"}, @@ -906,7 +996,7 @@ files = [ snowballstemmer = ">=2.2.0" [package.extras] -toml = ["tomli (>=1.2.3)"] +toml = ["tomli (>=1.2.3) ; python_version < \"3.11\""] [[package]] name = "pyflakes" @@ -914,6 +1004,8 @@ version = "2.5.0" description = "passive checker of Python programs" optional = false python-versions = ">=3.6" +groups = ["lint"] +markers = "python_version < \"3.12\"" files = [ {file = "pyflakes-2.5.0-py2.py3-none-any.whl", hash = "sha256:4579f67d887f804e67edb544428f264b7b24f435b263c4614f384135cea553d2"}, {file = "pyflakes-2.5.0.tar.gz", hash = "sha256:491feb020dca48ccc562a8c0cbe8df07ee13078df59813b83959cbdada312ea3"}, @@ -925,6 +1017,8 @@ version = "3.1.0" description = "passive checker of Python programs" optional = false python-versions = ">=3.8" +groups = ["lint"] +markers = "python_version >= \"3.12\"" files = [ {file = "pyflakes-3.1.0-py2.py3-none-any.whl", hash = "sha256:4132f6d49cb4dae6819e5379898f2b8cce3c5f23994194c24b77d5da2e36f774"}, {file = "pyflakes-3.1.0.tar.gz", hash = "sha256:a0aae034c444db0071aa077972ba4768d40c830d9539fd45bf4cd3f8f6992efc"}, @@ -936,6 +1030,7 @@ version = "2.19.2" description = "Pygments is a syntax highlighting package written in Python." optional = false python-versions = ">=3.8" +groups = ["lint", "test"] files = [ {file = "pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b"}, {file = "pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887"}, @@ -950,6 +1045,7 @@ version = "1.1.405" description = "Command line wrapper for pyright" optional = false python-versions = ">=3.7" +groups = ["lint"] files = [ {file = "pyright-1.1.405-py3-none-any.whl", hash = "sha256:a2cb13700b5508ce8e5d4546034cb7ea4aedb60215c6c33f56cec7f53996035a"}, {file = "pyright-1.1.405.tar.gz", hash = "sha256:5c2a30e1037af27eb463a1cc0b9f6d65fec48478ccf092c1ac28385a15c55763"}, @@ -971,6 +1067,7 @@ version = "8.4.1" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.9" +groups = ["test"] files = [ {file = "pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7"}, {file = "pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c"}, @@ -978,10 +1075,12 @@ files = [ [package.dependencies] colorama = {version = ">=0.4", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1", markers = "python_version < \"3.11\""} iniconfig = ">=1" packaging = ">=20" pluggy = ">=1.5,<2" pygments = ">=2.7.2" +tomli = {version = ">=1", markers = "python_version < \"3.11\""} [package.extras] dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "requests", "setuptools", "xmlschema"] @@ -992,6 +1091,7 @@ version = "6.2.1" description = "Pytest plugin for measuring coverage." optional = false python-versions = ">=3.9" +groups = ["test"] files = [ {file = "pytest_cov-6.2.1-py3-none-any.whl", hash = "sha256:f5bc4c23f42f1cdd23c70b1dab1bbaef4fc505ba950d53e0081d0730dd7e86d5"}, {file = "pytest_cov-6.2.1.tar.gz", hash = "sha256:25cc6cc0a5358204b8108ecedc51a9b57b34cc6b8c967cc2c01a4e00d8a67da2"}, @@ -1011,6 +1111,7 @@ version = "3.14.1" description = "Thin-wrapper around the mock package for easier use with pytest" optional = false python-versions = ">=3.8" +groups = ["test"] files = [ {file = "pytest_mock-3.14.1-py3-none-any.whl", hash = "sha256:178aefcd11307d874b4cd3100344e7e2d888d9791a6a1d9bfe90fbc1b74fd1d0"}, {file = "pytest_mock-3.14.1.tar.gz", hash = "sha256:159e9edac4c451ce77a5cdb9fc5d1100708d2dd4ba3c3df572f14097351af80e"}, @@ -1028,6 +1129,7 @@ version = "6.0.2" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.8" +groups = ["lint"] files = [ {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, @@ -1090,6 +1192,7 @@ version = "14.1.0" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" optional = false python-versions = ">=3.8.0" +groups = ["lint"] files = [ {file = "rich-14.1.0-py3-none-any.whl", hash = "sha256:536f5f1785986d6dbdea3c75205c473f970777b4a0d6c6dd1b696aa05a3fa04f"}, {file = "rich-14.1.0.tar.gz", hash = "sha256:e497a48b844b0320d45007cdebfeaeed8db2a4f4bcf49f15e455cfc4af11eaa8"}, @@ -1108,19 +1211,20 @@ version = "80.9.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.9" +groups = ["main", "lint"] files = [ {file = "setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922"}, {file = "setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c"}, ] [package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.8.0)"] -core = ["importlib_metadata (>=6)", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\"", "ruff (>=0.8.0) ; sys_platform != \"cygwin\""] +core = ["importlib_metadata (>=6) ; python_version < \"3.10\"", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1) ; python_version < \"3.11\"", "wheel (>=0.43.0)"] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] enabler = ["pytest-enabler (>=2.2)"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] -type = ["importlib_metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.14.*)", "pytest-mypy"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] +type = ["importlib_metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.develop (>=7.21) ; sys_platform != \"cygwin\"", "mypy (==1.14.*)", "pytest-mypy"] [[package]] name = "snowballstemmer" @@ -1128,6 +1232,7 @@ version = "3.0.1" description = "This package provides 32 stemmers for 30 languages generated from Snowball algorithms." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*" +groups = ["lint"] files = [ {file = "snowballstemmer-3.0.1-py3-none-any.whl", hash = "sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064"}, {file = "snowballstemmer-3.0.1.tar.gz", hash = "sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895"}, @@ -1139,6 +1244,7 @@ version = "5.4.1" description = "Manage dynamic plugins for Python applications" optional = false python-versions = ">=3.9" +groups = ["lint"] files = [ {file = "stevedore-5.4.1-py3-none-any.whl", hash = "sha256:d10a31c7b86cba16c1f6e8d15416955fc797052351a56af15e608ad20811fcfe"}, {file = "stevedore-5.4.1.tar.gz", hash = "sha256:3135b5ae50fe12816ef291baff420acb727fcd356106e3e9cbfa9e5985cd6f4b"}, @@ -1153,17 +1259,62 @@ version = "0.10.2" description = "Python Library for Tom's Obvious, Minimal Language" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +groups = ["lint"] files = [ {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, ] +[[package]] +name = "tomli" +version = "2.2.1" +description = "A lil' TOML parser" +optional = false +python-versions = ">=3.8" +groups = ["lint", "test"] +files = [ + {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, + {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"}, + {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"}, + {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"}, + {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"}, + {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"}, + {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"}, + {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"}, + {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}, + {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, +] +markers = {lint = "python_version < \"3.11\"", test = "python_full_version <= \"3.11.0a6\""} + [[package]] name = "types-protobuf" version = "6.30.2.20250703" description = "Typing stubs for protobuf" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "types_protobuf-6.30.2.20250703-py3-none-any.whl", hash = "sha256:fa5aff9036e9ef432d703abbdd801b436a249b6802e4df5ef74513e272434e57"}, {file = "types_protobuf-6.30.2.20250703.tar.gz", hash = "sha256:609a974754bbb71fa178fc641f51050395e8e1849f49d0420a6281ed8d1ddf46"}, @@ -1175,12 +1326,14 @@ version = "4.14.1" description = "Backported and Experimental Type Hints for Python 3.9+" optional = false python-versions = ">=3.9" +groups = ["lint", "test"] files = [ {file = "typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76"}, {file = "typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36"}, ] +markers = {test = "python_version < \"3.11\""} [metadata] -lock-version = "2.0" -python-versions = "^3.11" -content-hash = "62198fb6e7b89be209e8aaba32a6ca5104f2eb370978a5bca7c17578a405696b" +lock-version = "2.1" +python-versions = "^3.9" +content-hash = "c27e03f67cea4c2075d83fb4d71c87df1e75e256f4531c344050aacabc723ce8" diff --git a/tools/grpc_generator/pyproject.toml b/tools/grpc_generator/pyproject.toml index 79334630..948eaa25 100644 --- a/tools/grpc_generator/pyproject.toml +++ b/tools/grpc_generator/pyproject.toml @@ -12,8 +12,11 @@ grpc-generator = "grpc_generator.__main__:cli" generate-stubs = "grpc_generator.generate_stubs:main" [tool.poetry.dependencies] -python = "^3.11" -click = "^8.2.1" +python = "^3.9" +click = [ + { version = "^8.1.8", python = ">=3.9,<3.10" }, + { version = "^8.2.1", python = "^3.10" }, +] # When updating the grpcio-tools version, also update the minimum grpcio version # and regenerate gRPC stubs. grpcio-tools = [ From 800f211183e4ff9fcf964bcfd7449d76a2035c68 Mon Sep 17 00:00:00 2001 From: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> Date: Wed, 10 Sep 2025 13:36:36 -0700 Subject: [PATCH 07/19] Use if-elif instead of match to support Python 3.9 Signed-off-by: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> --- .../src/grpc_generator/generator.py | 38 +++++++++---------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/tools/grpc_generator/src/grpc_generator/generator.py b/tools/grpc_generator/src/grpc_generator/generator.py index f4fb00d5..6c4fbf94 100644 --- a/tools/grpc_generator/src/grpc_generator/generator.py +++ b/tools/grpc_generator/src/grpc_generator/generator.py @@ -114,21 +114,20 @@ def reset_python_package(generation_spec: GenerationSpec) -> None: if not generation_spec.package_folder.exists(): return - match generation_spec.output_format: - case OutputFormat.SUBPACKAGE: - # Only remove generated subpackage dirs. - # This allows for non-generated "mixin" subpackages. - dirs_to_remove = [] - for subpackage_dir in generation_spec.package_folder.iterdir(): - if is_generated_subpackage_dir(subpackage_dir): - dirs_to_remove.append(subpackage_dir) - - for dir_to_remove in dirs_to_remove: - shutil.rmtree(dir_to_remove) - case OutputFormat.SUBMODULE: - grpc_files = sorted(generation_spec.package_folder.glob("*_pb2.py*")) - grpc_files.extend(generation_spec.package_folder.glob("*_pb2_grpc.py*")) - remove_files(grpc_files) + if generation_spec.output_format == OutputFormat.SUBPACKAGE: + # Only remove generated subpackage dirs. + # This allows for non-generated "mixin" subpackages. + dirs_to_remove = [] + for subpackage_dir in generation_spec.package_folder.iterdir(): + if is_generated_subpackage_dir(subpackage_dir): + dirs_to_remove.append(subpackage_dir) + + for dir_to_remove in dirs_to_remove: + shutil.rmtree(dir_to_remove) + elif generation_spec.output_format == OutputFormat.SUBMODULE: + grpc_files = sorted(generation_spec.package_folder.glob("*_pb2.py*")) + grpc_files.extend(generation_spec.package_folder.glob("*_pb2_grpc.py*")) + remove_files(grpc_files) def generate_python_files(generation_spec: GenerationSpec) -> None: @@ -182,11 +181,10 @@ def finalize_python_package(generation_spec: GenerationSpec) -> None: ) remove_files(generation_spec.get_matching_service_files(relative_proto_file_path)) - match generation_spec.output_format: - case OutputFormat.SUBPACKAGE: - transform_files_for_namespace(generation_spec) - case OutputFormat.SUBMODULE: - add_submodule_files(generation_spec) + if generation_spec.output_format == OutputFormat.SUBPACKAGE: + transform_files_for_namespace(generation_spec) + elif generation_spec.output_format == OutputFormat.SUBMODULE: + add_submodule_files(generation_spec) generation_spec.package_descriptor_file.unlink() From 20a549a7b1cf1c6ba114776c6e2407cc70a4f2b1 Mon Sep 17 00:00:00 2001 From: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> Date: Wed, 10 Sep 2025 14:05:52 -0700 Subject: [PATCH 08/19] Use mixin enum for Python 3.9 and 3.10 Signed-off-by: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> --- tools/grpc_generator/src/grpc_generator/generator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/grpc_generator/src/grpc_generator/generator.py b/tools/grpc_generator/src/grpc_generator/generator.py index 6c4fbf94..bd65f886 100644 --- a/tools/grpc_generator/src/grpc_generator/generator.py +++ b/tools/grpc_generator/src/grpc_generator/generator.py @@ -1,10 +1,10 @@ """Generate gRPC Python stubs from proto files.""" +import enum import importlib.resources import pathlib import shutil from dataclasses import dataclass -from enum import StrEnum import click import grpc_tools.protoc # type: ignore[import-untyped] @@ -17,7 +17,7 @@ grpc-generator --proto-subpath ni/protobuf/types --output-basepath ../../packages/ni.protobuf.types/src --output-format submodule""" -class OutputFormat(StrEnum): +class OutputFormat(str, enum.Enum): """Supported Python output formats for generated gRPC packages.""" SUBMODULE = "submodule" From 5ff58341fb7c5549bea08972d4b848ebe1475ea1 Mon Sep 17 00:00:00 2001 From: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> Date: Wed, 10 Sep 2025 14:15:09 -0700 Subject: [PATCH 09/19] Tidy workflow titles Signed-off-by: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> --- .github/workflows/run_unit_tests.yml | 41 +--------------------------- .github/workflows/test_package.yml | 2 +- 2 files changed, 2 insertions(+), 41 deletions(-) diff --git a/.github/workflows/run_unit_tests.yml b/.github/workflows/run_unit_tests.yml index bbaaa553..4e112354 100644 --- a/.github/workflows/run_unit_tests.yml +++ b/.github/workflows/run_unit_tests.yml @@ -46,16 +46,13 @@ on: jobs: run_unit_tests: - name: Run unit tests for ${{ inputs.package-name }} on ${{ inputs.os }} + name: Run unit tests for ${{ inputs.package-name }} with ${{ inputs.python-version }} on ${{ inputs.os }} runs-on: ${{ inputs.os }} defaults: run: # Set the working-directory for all steps in this job. working-directory: ${{ github.workspace }}/${{ inputs.package-basepath }}/${{ inputs.package-name }} strategy: - # matrix: - # os: [windows-latest, ubuntu-latest] - # python-version: [3.9, '3.10', 3.11, 3.12, 3.13] # Fail-fast skews the pass/fail ratio and seems to make pytest produce # incomplete JUnit XML results. fail-fast: false @@ -78,39 +75,3 @@ jobs: package-basepath: ${{ inputs.package-basepath }} python-version: ${{ inputs.python-version }} os: ${{ inputs.os }} - - # - name: Run and upload unit tests - ni.protobuf.types - # uses: ./.github/actions/run_and_upload_unit_tests - # with: - # package-name: ni.protobuf.types - # - name: Run and upload unit tests - ni.panels.v1.proto - # uses: ./.github/actions/run_and_upload_unit_tests - # with: - # package-name: ni.panels.v1.proto - # - name: Run and upload unit tests - ni.measurementlink.measurement.v1.proto - # uses: ./.github/actions/run_and_upload_unit_tests - # with: - # package-name: ni.measurementlink.measurement.v1.proto - # - name: Run and upload unit tests - ni.measurementlink.measurement.v2.proto - # uses: ./.github/actions/run_and_upload_unit_tests - # with: - # package-name: ni.measurementlink.measurement.v2.proto - # - name: Run and upload unit tests - ni-grpc-extensions - # uses: ./.github/actions/run_and_upload_unit_tests - # with: - # package-name: ni-grpc-extensions - # - name: Run and upload unit tests - ni.measurementlink.discovery.v1.client - # uses: ./.github/actions/run_and_upload_unit_tests - # with: - # package-name: ni.measurementlink.discovery.v1.client - # - name: Run and upload unit tests - ni.measurementlink.pinmap.v1.client - # uses: ./.github/actions/run_and_upload_unit_tests - # with: - # package-name: ni.measurementlink.pinmap.v1.client - # # Run grpc_generator unit tests on its oldest supported version. - # - name: Run and upload unit tests - grpc_generator - # if: ${{ !contains(fromJSON('["3.9", "3.10"]'), matrix.python-version) }} - # uses: ./.github/actions/run_and_upload_unit_tests - # with: - # package-name: grpc_generator - # package-basepath: tools diff --git a/.github/workflows/test_package.yml b/.github/workflows/test_package.yml index 442e2fea..df8d7545 100644 --- a/.github/workflows/test_package.yml +++ b/.github/workflows/test_package.yml @@ -21,7 +21,7 @@ jobs: matrix: os: [windows-latest, ubuntu-latest] python-version: [3.9, '3.10', 3.11, 3.12, 3.13] - name: Run unit tests for ${{ inputs.package-name }} with ${{ matrix.python-version }} + name: Run unit tests for ${{ inputs.package-name }} with ${{ matrix.python-version }} on ${{ matrix.os }} needs: get_package_info uses: ./.github/workflows/run_unit_tests.yml with: From a9a8095656119b6b59094805c856dd114cf9fb06 Mon Sep 17 00:00:00 2001 From: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> Date: Wed, 10 Sep 2025 14:25:09 -0700 Subject: [PATCH 10/19] Upgrade grpc_generator to poetry 2.x Signed-off-by: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> --- tools/grpc_generator/poetry.lock | 4 ++-- tools/grpc_generator/pyproject.toml | 14 +++++++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/tools/grpc_generator/poetry.lock b/tools/grpc_generator/poetry.lock index dec7c403..09711392 100644 --- a/tools/grpc_generator/poetry.lock +++ b/tools/grpc_generator/poetry.lock @@ -1335,5 +1335,5 @@ markers = {test = "python_version < \"3.11\""} [metadata] lock-version = "2.1" -python-versions = "^3.9" -content-hash = "c27e03f67cea4c2075d83fb4d71c87df1e75e256f4531c344050aacabc723ce8" +python-versions = ">=3.9,<4.0" +content-hash = "76d271e192aefbb957794ee0555e9050acdd122056b0e49ef1d51247587a0ea6" diff --git a/tools/grpc_generator/pyproject.toml b/tools/grpc_generator/pyproject.toml index 948eaa25..56e03c51 100644 --- a/tools/grpc_generator/pyproject.toml +++ b/tools/grpc_generator/pyproject.toml @@ -1,18 +1,22 @@ -[tool.poetry] +[project] name = "ni-apis-grpc-generator" version = "0.1.0" license = "MIT" description = "Python generator for NI gRPC APIs" -authors = ["NI "] +authors = [{name = "NI", email = ""}] readme = "README.md" +dynamic = ["dependencies"] +requires-python = ">=3.9,<4.0" + +[tool.poetry] packages = [{include = "grpc_generator", from = "src"}] +requires-poetry = ">=2.1,<3.0" -[tool.poetry.scripts] +[project.scripts] grpc-generator = "grpc_generator.__main__:cli" generate-stubs = "grpc_generator.generate_stubs:main" [tool.poetry.dependencies] -python = "^3.9" click = [ { version = "^8.1.8", python = ">=3.9,<3.10" }, { version = "^8.2.1", python = "^3.10" }, @@ -38,7 +42,7 @@ pytest-cov = ">=4.0" pytest-mock = ">=3.0" [build-system] -requires = ["poetry-core>=1.8"] +requires = ["poetry-core>=2.1.0,<3.0"] build-backend = "poetry.core.masonry.api" From a9d5015328684684ae606d1674966ef06749b672 Mon Sep 17 00:00:00 2001 From: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> Date: Wed, 10 Sep 2025 14:30:51 -0700 Subject: [PATCH 11/19] Remove template refs that aren't filled when skipped Signed-off-by: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> --- .github/workflows/test_package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_package.yml b/.github/workflows/test_package.yml index df8d7545..61a2a557 100644 --- a/.github/workflows/test_package.yml +++ b/.github/workflows/test_package.yml @@ -21,7 +21,7 @@ jobs: matrix: os: [windows-latest, ubuntu-latest] python-version: [3.9, '3.10', 3.11, 3.12, 3.13] - name: Run unit tests for ${{ inputs.package-name }} with ${{ matrix.python-version }} on ${{ matrix.os }} + name: Run unit tests needs: get_package_info uses: ./.github/workflows/run_unit_tests.yml with: From 17b58081ccf27e5f8b21052f4526bc5494c733eb Mon Sep 17 00:00:00 2001 From: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> Date: Wed, 10 Sep 2025 14:41:44 -0700 Subject: [PATCH 12/19] Try moving the os/python matrix up one more level Signed-off-by: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> --- .github/workflows/CI.yml | 4 ++++ .github/workflows/test_package.yml | 17 +++++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 1437e5ef..d30ab806 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -27,9 +27,13 @@ jobs: strategy: matrix: package-name: ${{ fromJson(needs.get_package_names.outputs.package-names) }} + os: [windows-latest, ubuntu-latest] + python-version: [3.9, '3.10', 3.11, 3.12, 3.13] uses: ./.github/workflows/test_package.yml with: package-name: ${{ matrix.package-name }} + os: ${{ matrix.os }} + python-version: ${{ matrix.python-version }} report_test_results: name: Report test results uses: ./.github/workflows/report_test_results.yml diff --git a/.github/workflows/test_package.yml b/.github/workflows/test_package.yml index 61a2a557..24c7a0e9 100644 --- a/.github/workflows/test_package.yml +++ b/.github/workflows/test_package.yml @@ -8,6 +8,15 @@ on: default: '' required: true type: string + python-version: + description: 'The version of Python to use' + default: 3.11.9 + required: true + type: string + os: + description: 'The name of the OS to use' + required: true + type: string jobs: get_package_info: @@ -17,15 +26,11 @@ jobs: package-name: ${{ inputs.package-name }} run_unit_tests: if: ${{ needs.get_package_info.outputs.should-run-tests == 'true' }} - strategy: - matrix: - os: [windows-latest, ubuntu-latest] - python-version: [3.9, '3.10', 3.11, 3.12, 3.13] name: Run unit tests needs: get_package_info uses: ./.github/workflows/run_unit_tests.yml with: package-name: ${{ inputs.package-name }} package-basepath: ${{ needs.get_package_info.outputs.package-basepath }} - python-version: ${{ matrix.python-version }} - os: ${{ matrix.os }} + python-version: ${{ inputs.python-version }} + os: ${{ inputs.os }} From 431f7c573b27ad81cb240b2443fc41dd2e3837cd Mon Sep 17 00:00:00 2001 From: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> Date: Wed, 10 Sep 2025 14:48:16 -0700 Subject: [PATCH 13/19] Revert "Try moving the os/python matrix up one more level" - This makes get_package_info run for every os-python combo rather than once This reverts commit 17b58081ccf27e5f8b21052f4526bc5494c733eb. --- .github/workflows/CI.yml | 4 ---- .github/workflows/test_package.yml | 17 ++++++----------- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index d30ab806..1437e5ef 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -27,13 +27,9 @@ jobs: strategy: matrix: package-name: ${{ fromJson(needs.get_package_names.outputs.package-names) }} - os: [windows-latest, ubuntu-latest] - python-version: [3.9, '3.10', 3.11, 3.12, 3.13] uses: ./.github/workflows/test_package.yml with: package-name: ${{ matrix.package-name }} - os: ${{ matrix.os }} - python-version: ${{ matrix.python-version }} report_test_results: name: Report test results uses: ./.github/workflows/report_test_results.yml diff --git a/.github/workflows/test_package.yml b/.github/workflows/test_package.yml index 24c7a0e9..61a2a557 100644 --- a/.github/workflows/test_package.yml +++ b/.github/workflows/test_package.yml @@ -8,15 +8,6 @@ on: default: '' required: true type: string - python-version: - description: 'The version of Python to use' - default: 3.11.9 - required: true - type: string - os: - description: 'The name of the OS to use' - required: true - type: string jobs: get_package_info: @@ -26,11 +17,15 @@ jobs: package-name: ${{ inputs.package-name }} run_unit_tests: if: ${{ needs.get_package_info.outputs.should-run-tests == 'true' }} + strategy: + matrix: + os: [windows-latest, ubuntu-latest] + python-version: [3.9, '3.10', 3.11, 3.12, 3.13] name: Run unit tests needs: get_package_info uses: ./.github/workflows/run_unit_tests.yml with: package-name: ${{ inputs.package-name }} package-basepath: ${{ needs.get_package_info.outputs.package-basepath }} - python-version: ${{ inputs.python-version }} - os: ${{ inputs.os }} + python-version: ${{ matrix.python-version }} + os: ${{ matrix.os }} From 725263a638a1d8f371de855a8395646c02941362 Mon Sep 17 00:00:00 2001 From: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> Date: Wed, 10 Sep 2025 14:53:53 -0700 Subject: [PATCH 14/19] Run tests in parallel with checks Signed-off-by: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 1437e5ef..ef9ce0e1 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -23,7 +23,7 @@ jobs: package-name: ${{ matrix.package-name }} test_package: name: Test ${{ matrix.package-name }} - needs: [get_package_names, check_package] + needs: get_package_names strategy: matrix: package-name: ${{ fromJson(needs.get_package_names.outputs.package-names) }} From d83dfb3e8dbe93cbf15853fda1c5dc3cba74ca2f Mon Sep 17 00:00:00 2001 From: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> Date: Thu, 11 Sep 2025 07:48:27 -0700 Subject: [PATCH 15/19] Move workflow_dispatch to test_package Signed-off-by: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> --- .github/workflows/run_unit_tests.yml | 21 --------------------- .github/workflows/test_package.yml | 7 +++++++ 2 files changed, 7 insertions(+), 21 deletions(-) diff --git a/.github/workflows/run_unit_tests.yml b/.github/workflows/run_unit_tests.yml index 4e112354..ecfe2651 100644 --- a/.github/workflows/run_unit_tests.yml +++ b/.github/workflows/run_unit_tests.yml @@ -15,30 +15,9 @@ on: type: string python-version: description: 'The version of Python to use' - default: 3.11.9 - required: true - type: string - os: - description: 'The name of the OS to use' - required: true - type: string - workflow_dispatch: - inputs: - package-name: - description: 'The name of the package folder to check.' default: '' required: true type: string - package-basepath: - description: 'The base path of the package to check, relative to the repo root.' - default: '' - required: true - type: string - python-version: - description: 'The version of Python to use' - default: 3.11.9 - required: true - type: string os: description: 'The name of the OS to use' required: true diff --git a/.github/workflows/test_package.yml b/.github/workflows/test_package.yml index 61a2a557..3c2ef36f 100644 --- a/.github/workflows/test_package.yml +++ b/.github/workflows/test_package.yml @@ -8,6 +8,13 @@ on: default: '' required: true type: string + workflow_dispatch: + inputs: + package-name: + description: 'The name of the package folder to test.' + default: '' + required: true + type: string jobs: get_package_info: From a3714b83bde60716a4e62a30d934d4ec8a5a2c6d Mon Sep 17 00:00:00 2001 From: Joe F <114173023+jfriedri-ni@users.noreply.github.com> Date: Thu, 11 Sep 2025 08:39:47 -0700 Subject: [PATCH 16/19] Fix email format in pyproject.toml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- tools/grpc_generator/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/grpc_generator/pyproject.toml b/tools/grpc_generator/pyproject.toml index 56e03c51..a7967e7d 100644 --- a/tools/grpc_generator/pyproject.toml +++ b/tools/grpc_generator/pyproject.toml @@ -3,7 +3,7 @@ name = "ni-apis-grpc-generator" version = "0.1.0" license = "MIT" description = "Python generator for NI gRPC APIs" -authors = [{name = "NI", email = ""}] +authors = [{name = "NI", email = "opensource@ni.com"}] readme = "README.md" dynamic = ["dependencies"] requires-python = ">=3.9,<4.0" From 3bbe863fee3ac87e9ce3bcf55b38b4800119abd6 Mon Sep 17 00:00:00 2001 From: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> Date: Thu, 11 Sep 2025 09:56:02 -0700 Subject: [PATCH 17/19] Raise when the caller uses an invalid output format Signed-off-by: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> --- tools/grpc_generator/src/grpc_generator/generator.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/grpc_generator/src/grpc_generator/generator.py b/tools/grpc_generator/src/grpc_generator/generator.py index bd65f886..edd73f85 100644 --- a/tools/grpc_generator/src/grpc_generator/generator.py +++ b/tools/grpc_generator/src/grpc_generator/generator.py @@ -128,6 +128,8 @@ def reset_python_package(generation_spec: GenerationSpec) -> None: grpc_files = sorted(generation_spec.package_folder.glob("*_pb2.py*")) grpc_files.extend(generation_spec.package_folder.glob("*_pb2_grpc.py*")) remove_files(grpc_files) + else: + raise ValueError(f"Invalid output format: {generation_spec.output_format}") def generate_python_files(generation_spec: GenerationSpec) -> None: @@ -185,6 +187,8 @@ def finalize_python_package(generation_spec: GenerationSpec) -> None: transform_files_for_namespace(generation_spec) elif generation_spec.output_format == OutputFormat.SUBMODULE: add_submodule_files(generation_spec) + else: + raise ValueError(f"Invalid output format: {generation_spec.output_format}") generation_spec.package_descriptor_file.unlink() From 5ce4bb62af1449d5afc35dcb14c551d3ace69da8 Mon Sep 17 00:00:00 2001 From: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> Date: Thu, 11 Sep 2025 10:10:46 -0700 Subject: [PATCH 18/19] Use env.pythonVersion rather than an input Use runner information rather than an input Signed-off-by: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> --- .../actions/run_and_upload_unit_tests/action.yml | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/.github/actions/run_and_upload_unit_tests/action.yml b/.github/actions/run_and_upload_unit_tests/action.yml index 6574d00b..6f54081d 100644 --- a/.github/actions/run_and_upload_unit_tests/action.yml +++ b/.github/actions/run_and_upload_unit_tests/action.yml @@ -8,15 +8,12 @@ inputs: description: 'Relative path to the parent directory of the package.' required: false default: 'packages' - python-version: - description: 'The version of Python to use' - required: true - os: - description: 'The name of the OS to use' - required: true runs: using: "composite" steps: + - name: Get OS version + run: echo "osVersion=$ImageOS" >> "$GITHUB_ENV" + shell: bash - name: Cache ${{ inputs.package-name }} virtualenv uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 with: @@ -27,12 +24,12 @@ runs: working-directory: ${{ github.workspace }}/${{ inputs.package-basepath }}/${{ inputs.package-name }} shell: bash - name: Run ${{ inputs.package-name }} unit tests and code coverage - run: poetry run pytest ./tests/unit -v --cov=${{ inputs.package-name }} --junitxml=test_results/${{ inputs.package-name }}-${{ inputs.os }}-py${{ inputs.python-version }}.xml + run: poetry run pytest ./tests/unit -v --cov=${{ inputs.package-name }} --junitxml=test_results/${{ inputs.package-name }}-${{ env.osVersion }}-py${{ env.pythonVersion }}.xml working-directory: ${{ github.workspace }}/${{ inputs.package-basepath }}/${{ inputs.package-name }} shell: bash - name: Upload ${{ inputs.package-name }} test results uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: - name: test_results_unit_${{ inputs.package-name }}_${{ inputs.os }}_py${{ inputs.python-version }} + name: test_results_unit_${{ inputs.package-name }}_${{ env.osVersion }}_py${{ env.pythonVersion }} path: ${{ github.workspace }}/${{ inputs.package-basepath }}/${{ inputs.package-name }}/test_results/*.xml if: always() From a613d0d51d18a157c817b810f2bf07a12fcf0d33 Mon Sep 17 00:00:00 2001 From: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> Date: Thu, 11 Sep 2025 11:00:02 -0700 Subject: [PATCH 19/19] Remove unused inputs Signed-off-by: Joe Friedrichsen <114173023+jfriedri-ni@users.noreply.github.com> --- .github/workflows/run_unit_tests.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/run_unit_tests.yml b/.github/workflows/run_unit_tests.yml index ecfe2651..7f3a95d3 100644 --- a/.github/workflows/run_unit_tests.yml +++ b/.github/workflows/run_unit_tests.yml @@ -52,5 +52,3 @@ jobs: with: package-name: ${{ inputs.package-name }} package-basepath: ${{ inputs.package-basepath }} - python-version: ${{ inputs.python-version }} - os: ${{ inputs.os }}