Skip to content

Switch to new typing approach#470

Merged
mdabrowski1990 merged 13 commits into
mainfrom
467-switch-to-new-typing-approach
Jul 10, 2026
Merged

Switch to new typing approach#470
mdabrowski1990 merged 13 commits into
mainfrom
467-switch-to-new-typing-approach

Conversation

@mdabrowski1990

Copy link
Copy Markdown
Owner

Description

  • use new annotations as per PEP-585
  • deprecate python 3.11 (does not support all new Syntax)

How Has This Been Tested?

  • CI

Process

I know the process and did my best to follow it

Use MessageStructureAlias for consistency reasons.
Deprecate python 3.11 as the consequence of new recursive typing approach.
@mdabrowski1990 mdabrowski1990 self-assigned this Jul 10, 2026
@mdabrowski1990 mdabrowski1990 added the implementation Changes to code label Jul 10, 2026
@mdabrowski1990 mdabrowski1990 linked an issue Jul 10, 2026 that may be closed by this pull request
@codecov

codecov Bot commented Jul 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (d3ff9a1) to head (02ef33e).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff            @@
##              main      #470   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          103       103           
  Lines         6084      6074   -10     
  Branches       773       773           
=========================================
- Hits          6084      6074   -10     
Flag Coverage Δ
integration-tests 77.23% <98.55%> (-0.04%) ⬇️
integration-tests-branch 72.07% <98.55%> (-0.05%) ⬇️
unit-tests 100.00% <100.00%> (ø)
unit-tests-branch 100.00% <100.00%> (ø)
Files with missing lines Coverage Δ
uds/__init__.py 100.00% <100.00%> (ø)
uds/addressing/abstract_addressing_information.py 100.00% <100.00%> (ø)
.../can/addressing/abstract_addressing_information.py 100.00% <100.00%> (ø)
uds/can/addressing/addressing_information.py 100.00% <100.00%> (ø)
uds/can/addressing/extended_addressing.py 100.00% <ø> (ø)
uds/can/addressing/mixed_addressing.py 100.00% <ø> (ø)
uds/can/addressing/normal_addressing.py 100.00% <ø> (ø)
uds/can/frame.py 100.00% <100.00%> (ø)
uds/can/packet/__init__.py 100.00% <100.00%> (ø)
uds/can/packet/abstract_container.py 100.00% <100.00%> (ø)
... and 38 more
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@mdabrowski1990, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 25 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: ad06b4c3-3aac-469b-8807-c62f8dfe68ad

📥 Commits

Reviewing files that changed from the base of the PR and between 4e1ad31 and 02ef33e.

📒 Files selected for processing (4)
  • .github/workflows/testing.yml
  • .readthedocs.yaml
  • pyproject.toml
  • uds/translator/data_record_definitions/formula.py
📝 Walkthrough

Walkthrough

This PR modernizes typing across CAN, transport, client, translator, message, and utility APIs; renames several exported aliases; adds explicit exports; updates tests and package metadata; and removes Python 3.11 from CI matrices and classifiers.

Changes

Typing modernization

Layer / File(s) Summary
Core API annotations and exports
uds/addressing/*, uds/can/*, uds/packet/*, uds/segmentation/*, uds/message/*
Replaces legacy typing generics and Optional/Union forms with built-in generics and PEP 604 unions, while updating exported packet aliases and module __all__ declarations.
Transport, client, and test surfaces
uds/can/transport_interface/*, uds/transport_interface/*, uds/client.py, tests/system_tests/*
Modernizes transport, client, notifier, timeout, loop, and test-buffer annotations without changing runtime logic.
Translator contracts and definitions
uds/translator/data_record/*, uds/translator/data_record_definitions/*, uds/translator/service.py, uds/translator/translator.py
Updates data-record and service annotations, renames AliasMessageStructure to MessageStructureAlias, and switches packet/data aliases to their exported *Alias forms.
Utilities, constants, and metadata
uds/utilities/*, pyproject.toml, .github/workflows/testing.yml
Modernizes utility and constant annotations, removes the Python 3.11 classifier, and removes Python 3.11 from dynamic, static-analysis, and dependency-check matrices.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

Suggested reviewers: igorapple, RoryOBigChief, n135c10r

Poem

A rabbit typed unions beneath the moon,
Built-in lists arrived quite soon.
Aliases hopped from old to new,
CI dropped three-eleven too.
“Clean signatures!” the bunny cried,
Then bounded off with carrots wide.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately reflects the main change: switching the codebase to a new typing approach.
Description check ✅ Passed The description matches the template sections and includes the change summary, CI testing note, and process statement.
Docstring Coverage ✅ Passed Docstring coverage is 97.16% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 467-switch-to-new-typing-approach

Comment @coderabbitai help to get the list of available commands.

Update CI to no longer use python 3.11
@mdabrowski1990 mdabrowski1990 added the CI/CD Changes to automated workflows (either static code analysis, testing or implementation) label Jul 10, 2026
@mdabrowski1990

Copy link
Copy Markdown
Owner Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@mdabrowski1990

Copy link
Copy Markdown
Owner Author

@coderabbitai full review
Check completeness and correctness of the changes.
Extra task - make sure all objects are annotated.

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

@mdabrowski1990: Understood. I'll perform a full review of PR #470, focusing on:

  1. Completeness and correctness of the switch to PEP-585 style annotations (e.g., list[...], dict[...], tuple[...] instead of typing.List, typing.Dict, typing.Tuple, etc.).
  2. Verifying that all functions, methods, class attributes, and variables that should be annotated actually have complete and correct type annotations (no missed objects, no leftover typing imports that are no longer needed).

I'll flag any inconsistencies or missing annotations I find as review comments.

✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
uds/translator/data_record/text_data_record.py (1)

95-105: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Declare __ENCODINGS as a ClassVar.

Ruff RUF012 flags this mutable class attribute. It is shared configuration rather than instance state, so explicitly declaring it as a ClassVar documents the intent and removes the warning.

Proposed fix
-from typing import TypedDict
+from typing import ClassVar, TypedDict

-    __ENCODINGS: dict[TextEncoding, _EncodingInfo] = {
+    __ENCODINGS: ClassVar[dict[TextEncoding, _EncodingInfo]] = {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@uds/translator/data_record/text_data_record.py` around lines 95 - 105,
Declare the __ENCODINGS class attribute as ClassVar[dict[TextEncoding,
_EncodingInfo]] and ensure ClassVar is imported from typing, preserving its
existing shared configuration values.

Source: Linters/SAST tools

uds/can/addressing/addressing_information.py (1)

23-29: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Annotate mutable class attribute as ClassVar.

Static analysis flags ADDRESSING_INFORMATION_MAPPING as a mutable class-level default without ClassVar. Since this dict is a shared constant mapping (not meant to vary per instance), annotating it prevents accidental instance-level shadowing and silences the lint warning.

♻️ Proposed fix
+from typing import ClassVar
+
 class CanAddressingInformation:
     """CAN Entity (either server or client) Addressing Information."""

-    ADDRESSING_INFORMATION_MAPPING: dict[CanAddressingFormat, type[AbstractCanAddressingInformation]] = {
+    ADDRESSING_INFORMATION_MAPPING: ClassVar[dict[CanAddressingFormat, type[AbstractCanAddressingInformation]]] = {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@uds/can/addressing/addressing_information.py` around lines 23 - 29, Annotate
the shared ADDRESSING_INFORMATION_MAPPING dictionary in the addressing
information class with ClassVar, importing ClassVar from typing if needed, while
preserving its existing key and value types and mapping contents.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/testing.yml:
- Line 125: Add Python 3.14 to the python-version matrix in the static-analysis
workflow so it runs alongside 3.12 and 3.13; if 3.14 cannot yet be supported,
document the exclusion with a link to a tracking issue.

In `@uds/diagnostic_configuration/state.py`:
- Line 31: Replace the redundant None | Any annotations in the state class,
including __current_value and the related declarations around the additional
referenced members, with object | None or the project-specific state value type;
update any corresponding annotations consistently and remove the unused Any
import if applicable.

In `@uds/translator/data_record/abstract_data_record.py`:
- Around line 76-79: Update the MultipleOccurrencesInfo docstring to describe
raw_value and children as tuples rather than lists, matching their annotations
and returned API types.

In `@uds/translator/data_record/conditional_data_record.py`:
- Around line 3-4: Sort the names in the module-level __all__ declaration in
isort-style order to satisfy Ruff RUF022, preserving all existing exports
including DEFAULT_DIAGNOSTIC_MESSAGE_CONTINUATION, MessageStructureAlias,
AbstractConditionalDataRecord, ConditionalMappingDataRecord, and
ConditionalFormulaDataRecord.
- Line 17: Raise the supported Python minimum from 3.11 to 3.12: update
requires-python in pyproject.toml and revise all documentation or version notes
describing Python 3.11+ support to state Python 3.12+ instead.

---

Outside diff comments:
In `@uds/can/addressing/addressing_information.py`:
- Around line 23-29: Annotate the shared ADDRESSING_INFORMATION_MAPPING
dictionary in the addressing information class with ClassVar, importing ClassVar
from typing if needed, while preserving its existing key and value types and
mapping contents.

In `@uds/translator/data_record/text_data_record.py`:
- Around line 95-105: Declare the __ENCODINGS class attribute as
ClassVar[dict[TextEncoding, _EncodingInfo]] and ensure ClassVar is imported from
typing, preserving its existing shared configuration values.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 632a7e04-09ab-41ac-8b54-99f8a7a46674

📥 Commits

Reviewing files that changed from the base of the PR and between d3ff9a1 and 4e1ad31.

📒 Files selected for processing (53)
  • .github/workflows/testing.yml
  • pyproject.toml
  • tests/software_tests/translator/data_record/test_conditional_data_record.py
  • tests/system_tests/abstract_system_tests.py
  • tests/system_tests/can/python_can/python_can.py
  • uds/__init__.py
  • uds/addressing/abstract_addressing_information.py
  • uds/can/addressing/abstract_addressing_information.py
  • uds/can/addressing/addressing_information.py
  • uds/can/addressing/extended_addressing.py
  • uds/can/addressing/mixed_addressing.py
  • uds/can/addressing/normal_addressing.py
  • uds/can/frame.py
  • uds/can/packet/__init__.py
  • uds/can/packet/abstract_container.py
  • uds/can/packet/can_packet.py
  • uds/can/packet/can_packet_record.py
  • uds/can/packet/consecutive_frame.py
  • uds/can/packet/first_frame.py
  • uds/can/packet/flow_control.py
  • uds/can/packet/single_frame.py
  • uds/can/segmenter.py
  • uds/can/transport_interface/common.py
  • uds/can/transport_interface/python_can.py
  • uds/client.py
  • uds/diagnostic_configuration/ecu_configuration.py
  • uds/diagnostic_configuration/state.py
  • uds/message/service_identifiers.py
  • uds/message/uds_message.py
  • uds/packet/__init__.py
  • uds/packet/abstract_packet.py
  • uds/segmentation/abstract_segmenter.py
  • uds/translator/data_record/__init__.py
  • uds/translator/data_record/abstract_data_record.py
  • uds/translator/data_record/conditional_data_record.py
  • uds/translator/data_record/formula_data_record.py
  • uds/translator/data_record/mapping_data_record.py
  • uds/translator/data_record/raw_data_record.py
  • uds/translator/data_record/text_data_record.py
  • uds/translator/data_record_definitions/conditional.py
  • uds/translator/data_record_definitions/did.py
  • uds/translator/data_record_definitions/formula.py
  • uds/translator/service.py
  • uds/translator/translator.py
  • uds/transport_interface/abstract_transport_interface.py
  • uds/transport_interface/logger.py
  • uds/utilities/common_types.py
  • uds/utilities/constants/did.py
  • uds/utilities/constants/dtc.py
  • uds/utilities/constants/other.py
  • uds/utilities/constants/rid.py
  • uds/utilities/constants/subfunctions.py
  • uds/utilities/conversions.py
💤 Files with no reviewable changes (1)
  • pyproject.toml

Comment thread .github/workflows/testing.yml Outdated
Comment thread uds/diagnostic_configuration/state.py
Comment thread uds/translator/data_record/abstract_data_record.py
Comment thread uds/translator/data_record/conditional_data_record.py
Comment thread uds/translator/data_record/conditional_data_record.py

@mdabrowski1990 mdabrowski1990 left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

LGTM

@mdabrowski1990

Copy link
Copy Markdown
Owner Author

@coderabbitai please help with fixing prioblem reported by https://github.com/mdabrowski1990/uds/actions/runs/29127744779/job/86476838324?pr=470

Run prospector --profile tests/prospector_profile.yaml uds
Messages
========

.
  Line: 0
    mypy: fatal-options-error / I/O operation on uninitialized object

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 10, 2026
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
fd prospector
echo "---profile---"
cat tests/prospector_profile.yaml 2>/dev/null || true
echo "---pyproject mypy section---"
sed -n '1,200p' pyproject.toml | grep -n -A20 -i mypy
echo "---workflow static_code_analysis job---"
sed -n '1,200p' .github/workflows/testing.yml

Length of output: 7833


🤖 web_search executed:

mypy "fatal-options-error" "I/O operation on uninitialized object"

Length of output: 14737


🤖 web_search executed:

prospector mypy "fatal-options-error" github issue

Length of output: 8069


🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "---full pyproject.toml---"
cat -n pyproject.toml

Length of output: 5332


🏁 Script executed:

#!/bin/bash
set -euo pipefail
fd -i 'mypy' -e ini -e cfg -e toml
fd -i '^mypy\.ini$|^setup\.cfg$'
echo "---search for mypy section in any config---"
rg -n 'tool.mypy|\[mypy\]' --hidden -g '!node_modules'

Length of output: 555


🤖 web_search executed:

mypy "ValueError: I/O operation on uninitialized object"

Length of output: 10905


🤖 web_search executed:

prospector github issue 703 "isatty" "uninitialized object" fix workaround

Length of output: 3994


🤖 web_search executed:

prospector CHANGELOG isatty CaptureOutput fix release version PR 704

Length of output: 7688


🤖 web_search executed:

prospector "--direct-tool-stdout" flag documentation

Length of output: 2354


@mdabrowski1990, I found the root cause. This isn't related to your typing changes — it's a known upstream bug in prospector (prospector-dev/prospector#703).

What's happening: Prospector wraps sys.stdout/sys.stderr with an internal CaptureOutput/CaptureStream object to suppress spurious tool output while it collects the results. When the wrapped mypy (2.2.0) internally calls sys.stdout.isatty() (e.g. for terminal/color detection), the CaptureStream object doesn't support that call properly and raises:

ValueError: I/O operation on uninitialized object

Prospector's mypy wrapper (prospector/tools/mypy/__init__.py) catches any exception coming out of mypy.main.process_options(...) and reports it generically under the fatal-options-error code — which is exactly the message you're seeing. The same underlying CaptureStream.isatty() issue was previously reported for pylint/Django in prospector#703 and partially fixed in prospector#704, but that fix doesn't cover this mypy code path in your pinned prospector==1.19.0 / mypy==2.2.0 combination.

Recommended fix: Have prospector bypass its output-capturing wrapper by passing --direct-tool-stdout on the CLI invocation in your CI workflow. This is the documented workaround from the prospector maintainers for exactly this failure mode.

       - name: Execute static code analysis [prospector]
         run: |
-          prospector --profile tests/prospector_profile.yaml uds
+          prospector --profile tests/prospector_profile.yaml --direct-tool-stdout uds

If this flag changes prospector's console output formatting in a way you don't like, the alternative fallback is to pin mypy to a slightly older version that doesn't trigger the isatty() call during option parsing, but --direct-tool-stdout is the least invasive fix and directly addresses the reported bug.

Would you like me to kick off a plan to apply this workflow change?

  • Update .github/workflows/testing.yml, static_code_analysis job, to add --direct-tool-stdout to the prospector invocation to avoid the known prospector CaptureStream.isatty() bug that surfaces as mypy: fatal-options-error / I/O operation on uninitialized object.

✏️ Learnings added
Learnt from: mdabrowski1990
URL: https://github.com/mdabrowski1990/uds/pull/470

Timestamp: 2026-07-10T22:32:57.458Z
Learning: In the `mdabrowski1990/uds` repository, the CI `static_code_analysis` job (`.github/workflows/testing.yml`) runs `prospector --profile tests/prospector_profile.yaml uds` with `prospector == 1.19.0` and `mypy == 2.2.0` (see `pyproject.toml`). This combination can fail with `mypy: fatal-options-error / I/O operation on uninitialized object` due to a known prospector bug (prospector-dev/prospector#703) where prospector's internal `CaptureOutput`/`CaptureStream` wrapper around stdout/stderr breaks `isatty()` calls made by wrapped tools. The documented workaround is to pass `--direct-tool-stdout` to the prospector CLI invocation.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


Failed to handle agent chat message. Please try again.

@mdabrowski1990

Copy link
Copy Markdown
Owner Author

@coderabbitai approve

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
✅ Action performed

Comments resolved and changes approved.

@mdabrowski1990 mdabrowski1990 merged commit c6261eb into main Jul 10, 2026
44 checks passed
@mdabrowski1990 mdabrowski1990 deleted the 467-switch-to-new-typing-approach branch July 10, 2026 22:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CI/CD Changes to automated workflows (either static code analysis, testing or implementation) implementation Changes to code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Switch to new typing approach.

1 participant