The python - pullrequest (Build Analyze) CI job fails on every PR with 16 mypy errors in azure-eventhub. The errors are in main (not
introduced by any specific PR) — they reproduce locally on a clean clone with the same mypy invocation the CI uses:
mypy --python-version 3.10 --show-error-codes --ignore-missing-imports
sdk/eventhub/azure-eventhub/azure
Because these are pre-existing, every PR touching azure-eventhub ships with a red Build Analyze check, which makes it harder to spot regressions
introduced by the PR itself.
Errors
azure/eventhub/_common.py (12)
| Line |
Code |
Summary |
Suggested direction |
| 142, 143, 144 |
assignment |
__init__ does self.message_id = None / self.content_type = None / self.correlation_id = None, but the |
|
corresponding setters are typed value: str. |
Relax setter signatures to value: Optional[str]. The setters already accept None at runtime — |
|
|
| only the annotation is wrong. |
|
|
|
| 321, 340, 351 |
union-attr |
self._raw_amqp_message.annotations.get(...) when annotations is `dict |
None`. |
((annotations or {}).get(...)) or change AmqpAnnotatedMessage.annotations to non-Optional (since __init__ always sets annotations={}). |
|
|
|
| 330 |
index |
self._raw_amqp_message.annotations[PROP_OFFSET] — index on `dict |
None`. |
AttributeError)won't catch theTypeErroryou'd get fromNone[key]`. |
|
|
|
| 359 |
return-value |
application_properties property returns Dict[Union[str, bytes], Any] but |
|
self._raw_amqp_message.application_properties is `Dict |
None`. |
Return ... or {}, or change AmqpAnnotatedMessage.application_properties to |
|
| non-Optional. |
|
|
|
| 405 |
arg-type |
self._sys_properties.update(self._raw_amqp_message.annotations) — annotations may be None. |
`update(annotations or |
| {})`. |
|
|
|
| 489, 509, 531 |
union-attr |
Inside content_type / correlation_id / message_id setters: `self._raw_amqp_message.properties. = |
|
value. The preceding if not self._raw_amqp_message.properties: self._raw_amqp_message.properties = AmqpMessageProperties()` doesn't narrow |
|
|
|
| because mypy can't trust that two consecutive accesses to a property return the same value. |
Cache to local variable: `props = |
|
|
| self._raw_amqp_message.properties; if props is None: ... ; props. = value`. |
|
|
|
azure/eventhub/_producer.py (1)
| Line |
Code |
Summary |
Suggested direction |
| 135 |
arg-type |
keep_alive_interval=self._keep_alive where self._keep_alive is Any | None (defaults to None in __init__) but the |
|
abstract AmqpTransport.create_send_client annotates the kwarg as int. |
The pyamqp client at _pyamqp/client.py:174 already does `int(...) if |
|
|
... is not None else 0, so Noneis supported at runtime. Relax the ABC signature tokeep_alive_interval: Optional[int]`. |
|
|
|
azure/eventhub/_consumer.py (2)
| Line |
Code |
Summary |
Suggested direction |
| 132 |
arg-type |
create_source(self._source, self._offset, ...) — self._offset is Any | None from kwargs.get("event_position", None), |
|
but the ABC says offset: int. |
The ABC's int is wrong even before considering Optional: event_position accepts `Union[str, int, |
|
|
datetime.datetime]. Relax to offset: Optional[Union[str, int, datetime.datetime]]`. |
|
|
|
| 133 |
arg-type |
event_position_selector(self._offset, ...) — function annotated value: Union[str, int, datetime.datetime], no Optional. |
|
At runtime self._offset is always set before _create_handler runs (consumers go through EventHubConsumerClient which defaults to |
|
|
|
"@latest"). Two options: (a) tighten _offset type at consumer init by annotating event_position: Optional[...] = kwargs.get(...) and |
|
|
|
asserting non-None before this call, (b) relax event_position_selector to accept Optional with a documented fallback. |
|
|
|
azure/eventhub/aio/_consumer_async.py (1)
| Line |
Code |
Summary |
Suggested direction |
| 135 |
arg-type |
Same as _consumer.py:133. |
Mirror the fix chosen for the sync consumer. |
Repro
git checkout main
cd sdk/eventhub/azure-eventhub
python -m venv .venv && . .venv/bin/activate
pip install mypy==1.19.1 typing_extensions
python -m mypy --python-version 3.10 --show-error-codes --ignore-missing-imports azure
=> Found 16 errors in 4 files (checked 99 source files)
Why this matters
Every PR against azure-eventhub (and many PRs against unrelated SDK packages, depending on Azure Pipelines stage triggers) inherits a red Build
Analyze. PRs that introduce new mypy regressions in their changed files are easy to miss because the check is already red.
The
python - pullrequest (Build Analyze)CI job fails on every PR with 16 mypy errors inazure-eventhub. The errors are inmain(notintroduced by any specific PR) — they reproduce locally on a clean clone with the same mypy invocation the CI uses:
mypy --python-version 3.10 --show-error-codes --ignore-missing-imports
sdk/eventhub/azure-eventhub/azure
Because these are pre-existing, every PR touching
azure-eventhubships with a red Build Analyze check, which makes it harder to spot regressionsintroduced by the PR itself.
Errors
azure/eventhub/_common.py(12)assignment__init__doesself.message_id = None/self.content_type = None/self.correlation_id = None, but thevalue: str.value: Optional[str]. The setters already acceptNoneat runtime —union-attrself._raw_amqp_message.annotations.get(...)whenannotationsis `dict(annotations or {}).get(...)) or changeAmqpAnnotatedMessage.annotationsto non-Optional (since__init__always setsannotations={}).indexself._raw_amqp_message.annotations[PROP_OFFSET]— index on `dictwon't catch theTypeErroryou'd get fromNone[key]`.return-valueapplication_propertiesproperty returnsDict[Union[str, bytes], Any]butself._raw_amqp_message.application_propertiesis `Dict... or {}, or changeAmqpAnnotatedMessage.application_propertiestoarg-typeself._sys_properties.update(self._raw_amqp_message.annotations)—annotationsmay beNone.union-attrcontent_type/correlation_id/message_idsetters: `self._raw_amqp_message.properties. =. The precedingif not self._raw_amqp_message.properties: self._raw_amqp_message.properties = AmqpMessageProperties()` doesn't narrowazure/eventhub/_producer.py(1)arg-typekeep_alive_interval=self._keep_alivewhereself._keep_aliveisAny | None(defaults toNonein__init__) but theAmqpTransport.create_send_clientannotates the kwarg asint._pyamqp/client.py:174already does `int(...) if, soNoneis supported at runtime. Relax the ABC signature tokeep_alive_interval: Optional[int]`.azure/eventhub/_consumer.py(2)arg-typecreate_source(self._source, self._offset, ...)—self._offsetisAny | Nonefromkwargs.get("event_position", None),offset: int.intis wrong even before considering Optional:event_positionaccepts `Union[str, int,. Relax tooffset: Optional[Union[str, int, datetime.datetime]]`.arg-typeevent_position_selector(self._offset, ...)— function annotatedvalue: Union[str, int, datetime.datetime], noOptional.self._offsetis always set before_create_handlerruns (consumers go throughEventHubConsumerClientwhich defaults to"@latest"). Two options: (a) tighten_offsettype at consumer init by annotatingevent_position: Optional[...] = kwargs.get(...)andevent_position_selectorto accept Optional with a documented fallback.azure/eventhub/aio/_consumer_async.py(1)arg-type_consumer.py:133.Repro
git checkout main
cd sdk/eventhub/azure-eventhub
python -m venv .venv && . .venv/bin/activate
pip install mypy==1.19.1 typing_extensions
python -m mypy --python-version 3.10 --show-error-codes --ignore-missing-imports azure
=> Found 16 errors in 4 files (checked 99 source files)
Why this matters
Every PR against
azure-eventhub(and many PRs against unrelated SDK packages, depending on Azure Pipelines stage triggers) inherits a red BuildAnalyze. PRs that introduce new mypy regressions in their changed files are easy to miss because the check is already red.