Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add typing to aiokafka/record/* #1001

Merged
merged 10 commits into from
May 5, 2024
Merged

add typing to aiokafka/record/* #1001

merged 10 commits into from
May 5, 2024

Conversation

dimastbk
Copy link
Contributor

Changes

Fixes #

Checklist

  • I think the code is well written
  • Unit tests for the changes exist
  • Documentation reflects the changes
  • Add a new news fragment into the CHANGES folder
    • name it <issue_id>.<type> (e.g. 588.bugfix)
    • if you don't have an issue_id change it to the pr id after creating the PR
    • ensure type is one of the following:
      • .feature: Signifying a new feature.
      • .bugfix: Signifying a bug fix.
      • .doc: Signifying a documentation improvement.
      • .removal: Signifying a deprecation or removal of public API.
      • .misc: A ticket has been closed, but it is not of interest to users.
    • Make sure to use full sentences with correct case and punctuation, for example: Fix issue with non-ascii contents in doctest text files.

@dimastbk dimastbk marked this pull request as draft April 21, 2024 19:54
@dimastbk
Copy link
Contributor Author

Many differences between python and cython implementations.

aiokafka/record/_crecords/legacy_records.pyi:38: error: Class aiokafka.record._crecords.legacy_records.LegacyRecordBatch has abstract attributes "compression_type", "timestamp_type"  [misc]
aiokafka/record/_crecords/legacy_records.pyi:38: note: If it is meant to be abstract, add 'abc.ABCMeta' as an explicit metaclass
aiokafka/record/_crecords/legacy_records.pyi:38: error: Final class aiokafka.record._crecords.legacy_records.LegacyRecordBatch has abstract attributes "compression_type", "timestamp_type"  [misc]
aiokafka/record/_crecords/legacy_records.pyi:42: error: Function is missing a type annotation for one or more arguments  [no-untyped-def]
aiokafka/record/_crecords/legacy_records.pyi:49: error: Class aiokafka.record._crecords.legacy_records.LegacyRecordBatchBuilder has abstract attributes "size_in_bytes"  [misc]
aiokafka/record/_crecords/legacy_records.pyi:49: note: If it is meant to be abstract, add 'abc.ABCMeta' as an explicit metaclass
aiokafka/record/_crecords/legacy_records.pyi:49: error: Final class aiokafka.record._crecords.legacy_records.LegacyRecordBatchBuilder has abstract attributes "size_in_bytes"  [misc]
aiokafka/record/_crecords/default_records.pyi:17: error: Incompatible types in assignment (expression has type "Sequence[Tuple[str, Optional[bytes]]]", base class "DefaultRecordProtocol" defined the type as "List[Tuple[str, Optional[bytes]]]")  [assignment]
aiokafka/record/_crecords/default_records.pyi:30: error: Signature of "timestamp" incompatible with supertype "DefaultRecordProtocol"  [override]
aiokafka/record/_crecords/default_records.pyi:30: note:      Superclass:
aiokafka/record/_crecords/default_records.pyi:30: note:          int
aiokafka/record/_crecords/default_records.pyi:30: note:      Subclass:
aiokafka/record/_crecords/default_records.pyi:30: note:          Optional[int]
aiokafka/record/_crecords/default_records.pyi:32: error: Signature of "timestamp_type" incompatible with supertype "DefaultRecordProtocol"  [override]
aiokafka/record/_crecords/default_records.pyi:32: note:      Superclass:
aiokafka/record/_crecords/default_records.pyi:32: note:          int
aiokafka/record/_crecords/default_records.pyi:32: note:      Subclass:
aiokafka/record/_crecords/default_records.pyi:32: note:          Optional[int]
aiokafka/record/_crecords/default_records.pyi:35: error: Class aiokafka.record._crecords.default_records.DefaultRecordBatch has abstract attributes "attributes", "base_offset", "base_sequence", "crc", "first_timestamp", "last_offset_delta", "magic", "max_timestamp", "next", "producer_epoch", "producer_id", "timestamp_type"  [misc]
aiokafka/record/_crecords/default_records.pyi:35: note: If it is meant to be abstract, add 'abc.ABCMeta' as an explicit metaclass
aiokafka/record/_crecords/default_records.pyi:35: error: Final class aiokafka.record._crecords.default_records.DefaultRecordBatch has abstract attributes "attributes", "base_offset", "base_sequence", "crc", "first_timestamp", "last_offset_delta", "magic", "max_timestamp", "next", "producer_epoch", "producer_id", "timestamp_type"  [misc]
aiokafka/record/_crecords/default_records.pyi:50: error: Class aiokafka.record._crecords.default_records.DefaultRecordBatchBuilder has abstract attributes "write_header"  [misc]
aiokafka/record/_crecords/default_records.pyi:50: note: If it is meant to be abstract, add 'abc.ABCMeta' as an explicit metaclass
aiokafka/record/_crecords/default_records.pyi:50: error: Final class aiokafka.record._crecords.default_records.DefaultRecordBatchBuilder has abstract attributes "write_header"  [misc]
aiokafka/record/_crecords/default_records.pyi:101: error: Class aiokafka.record._crecords.default_records.DefaultRecordMetadata has abstract attributes "crc"  [misc]
aiokafka/record/_crecords/default_records.pyi:101: note: If it is meant to be abstract, add 'abc.ABCMeta' as an explicit metaclass
aiokafka/record/_crecords/default_records.pyi:101: error: Final class aiokafka.record._crecords.default_records.DefaultRecordMetadata has abstract attributes "crc"  [misc]
aiokafka/record/util.py:148: error: Incompatible types in assignment (expression has type "Callable[[Buffer], int]", variable has type "Callable[[Union[array[int], bytes, bytearray, Iterable[int]]], int]")  [assignment]
aiokafka/record/legacy_records.py:474: error: Cannot determine type of "_buffer"  [has-type]
aiokafka/record/legacy_records.py:489: error: Cannot determine type of "_buffer"  [has-type]
aiokafka/record/legacy_records.py:599: error: Can only assign concrete classes to a variable of type "Type[LegacyRecordBatchBuilderProtocol]"  [type-abstract]
aiokafka/record/legacy_records.py:601: error: Can only assign concrete classes to a variable of type "Type[LegacyRecordBatchProtocol]"  [type-abstract]
aiokafka/record/default_records.py:548: error: Unsupported operand types for > ("int" and "None")  [operator]
aiokafka/record/default_records.py:548: note: Left operand is of type "Optional[int]"
aiokafka/record/default_records.py:758: error: Can only assign concrete classes to a variable of type "Type[DefaultRecordBatchBuilderProtocol]"  [type-abstract]
aiokafka/record/default_records.py:759: error: Can only assign concrete classes to a variable of type "Type[DefaultRecordMetadataProtocol]"  [type-abstract]
aiokafka/record/default_records.py:760: error: Can only assign concrete classes to a variable of type "Type[DefaultRecordBatchProtocol]"  [type-abstract]
Found 23 errors in 5 files (checked 35 source files)

Copy link

@github-advanced-security github-advanced-security bot left a comment

Choose a reason for hiding this comment

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

CodeQL found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.

Makefile Outdated Show resolved Hide resolved
aiokafka/record/_crc32c.py Outdated Show resolved Hide resolved
aiokafka/record/_crecords/legacy_records.pyi Show resolved Hide resolved
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could you describe the idea with protocols? I'd rather try to avoid them, as they break code navigation

Copy link
Contributor Author

@dimastbk dimastbk Apr 24, 2024

Choose a reason for hiding this comment

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

What alternatives? I did attempt to use Union instead of Protocol (last commit) - it's hard for mypy:

tests/record/test_records.py:70: error: "object" has no attribute "value"  [attr-defined]
tests/record/test_records.py:71: error: "object" has no attribute "key"  [attr-defined]
tests/record/test_records.py:72: error: "object" has no attribute "timestamp"  [attr-defined]
tests/record/test_records.py:73: error: "object" has no attribute "timestamp_type"  [attr-defined]
tests/record/test_records.py:74: error: "object" has no attribute "checksum"  [attr-defined]
tests/record/test_records.py:75: error: "object" has no attribute "headers"  [attr-defined]
tests/record/test_records.py:96: error: "object" has no attribute "value"  [attr-defined]
tests/record/test_records.py:97: error: "object" has no attribute "key"  [attr-defined]
tests/record/test_records.py:98: error: "object" has no attribute "timestamp"  [attr-defined]
tests/record/test_records.py:99: error: "object" has no attribute "timestamp_type"  [attr-defined]
tests/record/test_records.py:100: error: "object" has no attribute "checksum"  [attr-defined]
tests/record/test_records.py:124: error: "object" has no attribute "value"  [attr-defined]
tests/record/test_records.py:125: error: "object" has no attribute "key"  [attr-defined]
tests/record/test_records.py:126: error: "object" has no attribute "timestamp"  [attr-defined]
tests/record/test_records.py:127: error: "object" has no attribute "timestamp_type"  [attr-defined]
tests/record/test_records.py:128: error: "object" has no attribute "checksum"  [attr-defined]
tests/record/test_legacy.py:48: error: "object" has no attribute "offset"  [attr-defined]
tests/record/test_legacy.py:49: error: "object" has no attribute "timestamp"  [attr-defined]
tests/record/test_legacy.py:50: error: "object" has no attribute "timestamp_type"  [attr-defined]
tests/record/test_legacy.py:51: error: "object" has no attribute "key"  [attr-defined]
tests/record/test_legacy.py:52: error: "object" has no attribute "value"  [attr-defined]
tests/record/test_legacy.py:53: error: "object" has no attribute "checksum"  [attr-defined]
tests/record/test_legacy.py:91: error: "object" has no attribute "offset"  [attr-defined]
tests/record/test_legacy.py:92: error: "object" has no attribute "timestamp"  [attr-defined]
tests/record/test_legacy.py:93: error: "object" has no attribute "timestamp_type"  [attr-defined]
tests/record/test_legacy.py:94: error: "object" has no attribute "key"  [attr-defined]
tests/record/test_legacy.py:95: error: "object" has no attribute "value"  [attr-defined]
tests/record/test_legacy.py:96: error: "object" has no attribute "checksum"  [attr-defined]
tests/record/test_legacy.py:293: error: "object" has no attribute "offset"  [attr-defined]
tests/record/test_legacy.py:294: error: "object" has no attribute "timestamp"  [attr-defined]
tests/record/test_legacy.py:295: error: "object" has no attribute "timestamp_type"  [attr-defined]
tests/record/test_legacy.py:314: error: "object" has no attribute "offset"  [attr-defined]
tests/record/test_legacy.py:315: error: "object" has no attribute "timestamp"  [attr-defined]
tests/record/test_legacy.py:316: error: "object" has no attribute "timestamp_type"  [attr-defined]
tests/record/test_legacy.py:317: error: "object" has no attribute "key"  [attr-defined]
tests/record/test_legacy.py:318: error: "object" has no attribute "value"  [attr-defined]
tests/record/test_legacy.py:319: error: "object" has no attribute "checksum"  [attr-defined]
tests/record/test_default_records.py:67: error: "object" has no attribute "offset"  [attr-defined]
tests/record/test_default_records.py:68: error: "object" has no attribute "timestamp"  [attr-defined]
tests/record/test_default_records.py:69: error: "object" has no attribute "key"  [attr-defined]
tests/record/test_default_records.py:70: error: "object" has no attribute "value"  [attr-defined]
tests/record/test_default_records.py:71: error: "object" has no attribute "headers"  [attr-defined]

Copy link
Collaborator

Choose a reason for hiding this comment

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

Just checked for the first set of errors. Looks like mypy fails to infer type in such a complicated chain. But changing recs = tuple(batch) (which doesn't make sense anyway) to a simple unpack [rec] = batch solves the problem. Not sure this a right way though.

Copy link
Contributor Author

@dimastbk dimastbk Apr 28, 2024

Choose a reason for hiding this comment

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

It's ok for this case but we should use cast in a loop over union type, see python/mypy#8586

Copy link

codecov bot commented Apr 25, 2024

Codecov Report

Attention: Patch coverage is 85.47619% with 61 lines in your changes are missing coverage. Please review.

Project coverage is 95.04%. Comparing base (1862620) to head (0c3200b).

Files Patch % Lines
aiokafka/record/_protocols.py 59.71% 0 Missing and 56 partials ⚠️
aiokafka/record/default_records.py 96.66% 2 Missing and 1 partial ⚠️
aiokafka/record/legacy_records.py 97.40% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1001      +/-   ##
==========================================
- Coverage   95.36%   95.04%   -0.32%     
==========================================
  Files         112      114       +2     
  Lines       16751    16917     +166     
  Branches     2694     2757      +63     
==========================================
+ Hits        15974    16079     +105     
- Misses        489      493       +4     
- Partials      288      345      +57     
Flag Coverage Δ
cext 91.96% <79.76%> (-0.14%) ⬇️
integration 94.69% <85.47%> (-0.32%) ⬇️
purepy 94.52% <85.47%> (-0.31%) ⬇️
unit 52.78% <85.47%> (+0.11%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@dimastbk dimastbk marked this pull request as ready for review April 25, 2024 13:56
@ods ods merged commit c759664 into aio-libs:master May 5, 2024
29 of 31 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants