From cee416449701b72e7fd532585a1f739b02b6ab32 Mon Sep 17 00:00:00 2001 From: Tres Seaver Date: Thu, 18 Nov 2021 17:32:35 -0500 Subject: [PATCH] feat: add 'py.typed' declaration file (#287) Check typing using new 'mypy' nox session. --- google/__init__.py | 2 +- google/_async_resumable_media/_upload.py | 2 +- .../requests/_request_helpers.py | 4 ++-- .../requests/download.py | 2 +- .../_async_resumable_media/requests/upload.py | 2 +- google/resumable_media/_helpers.py | 4 ++-- google/resumable_media/_upload.py | 2 +- google/resumable_media/common.py | 2 +- google/resumable_media/py.typed | 2 ++ .../requests/_request_helpers.py | 2 +- google/resumable_media/requests/download.py | 2 +- google/resumable_media/requests/upload.py | 2 +- mypy.ini | 3 +++ noxfile.py | 13 +++++++++++ tests/system/requests/conftest.py | 6 ++--- tests/system/requests/test_download.py | 6 ++--- tests/system/requests/test_upload.py | 2 +- tests/system/utils.py | 2 +- tests/unit/requests/test__helpers.py | 4 ++-- tests/unit/requests/test_download.py | 2 +- tests/unit/test__download.py | 2 +- tests/unit/test__helpers.py | 2 +- tests/unit/test__upload.py | 22 +++++++++---------- tests/unit/test_common.py | 2 +- tests_async/system/requests/conftest.py | 6 ++--- tests_async/system/requests/test_download.py | 8 +++---- tests_async/system/requests/test_upload.py | 2 +- tests_async/unit/requests/test__helpers.py | 4 ++-- tests_async/unit/requests/test_download.py | 4 ++-- tests_async/unit/requests/test_upload.py | 6 ++--- tests_async/unit/test__download.py | 4 ++-- tests_async/unit/test__helpers.py | 2 +- tests_async/unit/test__upload.py | 22 +++++++++---------- 33 files changed, 85 insertions(+), 67 deletions(-) create mode 100644 google/resumable_media/py.typed create mode 100644 mypy.ini diff --git a/google/__init__.py b/google/__init__.py index 7c2cea5a..690df335 100644 --- a/google/__init__.py +++ b/google/__init__.py @@ -19,4 +19,4 @@ except ImportError: import pkgutil - __path__ = pkgutil.extend_path(__path__, __name__) + __path__ = pkgutil.extend_path(__path__, __name__) # type: ignore diff --git a/google/_async_resumable_media/_upload.py b/google/_async_resumable_media/_upload.py index 9c207a79..9f5b0de1 100644 --- a/google/_async_resumable_media/_upload.py +++ b/google/_async_resumable_media/_upload.py @@ -612,7 +612,7 @@ def _make_invalid(self): """ self._invalid = True - async def _process_response(self, response, bytes_sent): + async def _process_resumable_response(self, response, bytes_sent): """Process the response from an HTTP request. This is everything that must be done after a request that doesn't diff --git a/google/_async_resumable_media/requests/_request_helpers.py b/google/_async_resumable_media/requests/_request_helpers.py index f628ea46..4b2bb5cd 100644 --- a/google/_async_resumable_media/requests/_request_helpers.py +++ b/google/_async_resumable_media/requests/_request_helpers.py @@ -23,8 +23,8 @@ from google._async_resumable_media import _helpers from google.resumable_media import common -import google.auth.transport._aiohttp_requests as aiohttp_requests -import aiohttp +from google.auth.transport import _aiohttp_requests as aiohttp_requests # type: ignore +import aiohttp # type: ignore _DEFAULT_RETRY_STRATEGY = common.RetryStrategy() _SINGLE_GET_CHUNK_SIZE = 8192 diff --git a/google/_async_resumable_media/requests/download.py b/google/_async_resumable_media/requests/download.py index e88bac80..2b3e48ce 100644 --- a/google/_async_resumable_media/requests/download.py +++ b/google/_async_resumable_media/requests/download.py @@ -14,7 +14,7 @@ """Support for downloading media from Google APIs.""" -import urllib3.response +import urllib3.response # type: ignore from google._async_resumable_media import _download from google._async_resumable_media import _helpers diff --git a/google/_async_resumable_media/requests/upload.py b/google/_async_resumable_media/requests/upload.py index 4c6e79fb..363a7ac4 100644 --- a/google/_async_resumable_media/requests/upload.py +++ b/google/_async_resumable_media/requests/upload.py @@ -481,7 +481,7 @@ async def transmit_next_chunk( retry_strategy=self._retry_strategy, timeout=timeout, ) - await self._process_response(response, len(payload)) + await self._process_resumable_response(response, len(payload)) return response async def recover(self, transport): diff --git a/google/resumable_media/_helpers.py b/google/resumable_media/_helpers.py index d4747bf9..dc6fdaf1 100644 --- a/google/resumable_media/_helpers.py +++ b/google/resumable_media/_helpers.py @@ -140,12 +140,12 @@ def _get_crc32c_object(): to use CRCMod. CRCMod might be using a 'slow' varietal. If so, warn... """ try: - import google_crc32c + import google_crc32c # type: ignore crc_obj = google_crc32c.Checksum() except ImportError: try: - import crcmod + import crcmod # type: ignore crc_obj = crcmod.predefined.Crc("crc-32c") _is_fast_crcmod() diff --git a/google/resumable_media/_upload.py b/google/resumable_media/_upload.py index 34296fda..9cf40202 100644 --- a/google/resumable_media/_upload.py +++ b/google/resumable_media/_upload.py @@ -647,7 +647,7 @@ def _make_invalid(self): """ self._invalid = True - def _process_response(self, response, bytes_sent): + def _process_resumable_response(self, response, bytes_sent): """Process the response from an HTTP request. This is everything that must be done after a request that doesn't diff --git a/google/resumable_media/common.py b/google/resumable_media/common.py index 808278b8..25555ea5 100644 --- a/google/resumable_media/common.py +++ b/google/resumable_media/common.py @@ -26,7 +26,7 @@ UPLOAD_CHUNK_SIZE = 262144 # 256 * 1024 """int: Chunks in a resumable upload must come in multiples of 256 KB.""" -PERMANENT_REDIRECT = http.client.PERMANENT_REDIRECT +PERMANENT_REDIRECT = http.client.PERMANENT_REDIRECT # type: ignore """int: Permanent redirect status code. .. note:: diff --git a/google/resumable_media/py.typed b/google/resumable_media/py.typed new file mode 100644 index 00000000..7705b065 --- /dev/null +++ b/google/resumable_media/py.typed @@ -0,0 +1,2 @@ +# Marker file for PEP 561. +# The google-resumable_media package uses inline types. diff --git a/google/resumable_media/requests/_request_helpers.py b/google/resumable_media/requests/_request_helpers.py index d473ff85..5edfd7a5 100644 --- a/google/resumable_media/requests/_request_helpers.py +++ b/google/resumable_media/requests/_request_helpers.py @@ -18,7 +18,7 @@ """ import requests.exceptions -import urllib3.exceptions +import urllib3.exceptions # type: ignore import time diff --git a/google/resumable_media/requests/download.py b/google/resumable_media/requests/download.py index bcedc569..d5b130a0 100644 --- a/google/resumable_media/requests/download.py +++ b/google/resumable_media/requests/download.py @@ -14,7 +14,7 @@ """Support for downloading media from Google APIs.""" -import urllib3.response +import urllib3.response # type: ignore from google.resumable_media import _download from google.resumable_media import common diff --git a/google/resumable_media/requests/upload.py b/google/resumable_media/requests/upload.py index df8177bf..b565d7aa 100644 --- a/google/resumable_media/requests/upload.py +++ b/google/resumable_media/requests/upload.py @@ -508,7 +508,7 @@ def retriable_request(): method, url, data=payload, headers=headers, timeout=timeout ) - self._process_response(result, len(payload)) + self._process_resumable_response(result, len(payload)) return result diff --git a/mypy.ini b/mypy.ini new file mode 100644 index 00000000..4505b485 --- /dev/null +++ b/mypy.ini @@ -0,0 +1,3 @@ +[mypy] +python_version = 3.6 +namespace_packages = True diff --git a/noxfile.py b/noxfile.py index 454afe93..49277c16 100644 --- a/noxfile.py +++ b/noxfile.py @@ -188,6 +188,19 @@ def blacken(session): ) +@nox.session(python=DEFAULT_PYTHON_VERSION) +def mypy(session): + """Verify type hints are mypy compatible.""" + session.install("-e", ".") + session.install( + "mypy", + "types-setuptools", + "types-requests", + "types-mock", + ) + session.run("mypy", "google/", "tests/", "tests_async/") + + @nox.session(python=SYSTEM_TEST_PYTHON_VERSIONS) def system(session): """Run the system test suite.""" diff --git a/tests/system/requests/conftest.py b/tests/system/requests/conftest.py index e22229a5..9f160000 100644 --- a/tests/system/requests/conftest.py +++ b/tests/system/requests/conftest.py @@ -13,9 +13,9 @@ # limitations under the License. """py.test fixtures to be shared across multiple system test modules.""" -import google.auth -import google.auth.transport.requests as tr_requests -import pytest +import google.auth # type: ignore +import google.auth.transport.requests as tr_requests # type: ignore +import pytest # type: ignore from tests.system import utils diff --git a/tests/system/requests/test_download.py b/tests/system/requests/test_download.py index 15d3cbfd..d2d69f06 100644 --- a/tests/system/requests/test_download.py +++ b/tests/system/requests/test_download.py @@ -19,9 +19,9 @@ import io import os -import google.auth -import google.auth.transport.requests as tr_requests -import pytest +import google.auth # type: ignore +import google.auth.transport.requests as tr_requests # type: ignore +import pytest # type: ignore from google.resumable_media import common import google.resumable_media.requests as resumable_requests diff --git a/tests/system/requests/test_upload.py b/tests/system/requests/test_upload.py index e068c4e6..3dc92077 100644 --- a/tests/system/requests/test_upload.py +++ b/tests/system/requests/test_upload.py @@ -19,7 +19,7 @@ import os import urllib.parse -import pytest +import pytest # type: ignore import mock from google.resumable_media import common diff --git a/tests/system/utils.py b/tests/system/utils.py index 3884d0c9..87a5faa3 100644 --- a/tests/system/utils.py +++ b/tests/system/utils.py @@ -16,7 +16,7 @@ import hashlib import time -from test_utils.retry import RetryResult +from test_utils.retry import RetryResult # type: ignore BUCKET_NAME = "grpm-systest-{}".format(int(1000 * time.time())) diff --git a/tests/unit/requests/test__helpers.py b/tests/unit/requests/test__helpers.py index 7e84482c..2d5d1950 100644 --- a/tests/unit/requests/test__helpers.py +++ b/tests/unit/requests/test__helpers.py @@ -15,10 +15,10 @@ import http.client import mock -import pytest +import pytest # type: ignore import requests.exceptions -import urllib3.exceptions +import urllib3.exceptions # type: ignore from google.resumable_media import common from google.resumable_media.requests import _request_helpers diff --git a/tests/unit/requests/test_download.py b/tests/unit/requests/test_download.py index fd430ef7..df12ca44 100644 --- a/tests/unit/requests/test_download.py +++ b/tests/unit/requests/test_download.py @@ -16,7 +16,7 @@ import io import mock -import pytest +import pytest # type: ignore from google.resumable_media import common from google.resumable_media import _helpers diff --git a/tests/unit/test__download.py b/tests/unit/test__download.py index 8c86f252..46026b16 100644 --- a/tests/unit/test__download.py +++ b/tests/unit/test__download.py @@ -16,7 +16,7 @@ import io import mock -import pytest +import pytest # type: ignore from google.resumable_media import _download from google.resumable_media import common diff --git a/tests/unit/test__helpers.py b/tests/unit/test__helpers.py index fed70baf..fdb9c77f 100644 --- a/tests/unit/test__helpers.py +++ b/tests/unit/test__helpers.py @@ -18,7 +18,7 @@ import http.client import mock -import pytest +import pytest # type: ignore from google.resumable_media import _helpers from google.resumable_media import common diff --git a/tests/unit/test__upload.py b/tests/unit/test__upload.py index 6758c14f..2c2ca924 100644 --- a/tests/unit/test__upload.py +++ b/tests/unit/test__upload.py @@ -17,7 +17,7 @@ import sys import mock -import pytest +import pytest # type: ignore from google.resumable_media import _helpers from google.resumable_media import _upload @@ -705,7 +705,7 @@ def test__make_invalid(self): upload._make_invalid() assert upload.invalid - def test__process_response_bad_status(self): + def test__process_resumable_response_bad_status(self): upload = _upload.ResumableUpload(RESUMABLE_URL, ONE_MB) _fix_up_virtual(upload) @@ -713,7 +713,7 @@ def test__process_response_bad_status(self): assert not upload.invalid response = _make_response(status_code=http.client.NOT_FOUND) with pytest.raises(common.InvalidResponse) as exc_info: - upload._process_response(response, None) + upload._process_resumable_response(response, None) error = exc_info.value assert error.response is response @@ -724,7 +724,7 @@ def test__process_response_bad_status(self): # Make sure the upload is invalid after the failure. assert upload.invalid - def test__process_response_success(self): + def test__process_resumable_response_success(self): upload = _upload.ResumableUpload(RESUMABLE_URL, ONE_MB) _fix_up_virtual(upload) @@ -743,13 +743,13 @@ def test__process_response_success(self): status_code=http.client.OK, spec=["content", "status_code"], ) - ret_val = upload._process_response(response, bytes_sent) + ret_val = upload._process_resumable_response(response, bytes_sent) assert ret_val is None # Check status after. assert upload._bytes_uploaded == total_bytes assert upload._finished - def test__process_response_partial_no_range(self): + def test__process_resumable_response_partial_no_range(self): upload = _upload.ResumableUpload(RESUMABLE_URL, ONE_MB) _fix_up_virtual(upload) @@ -757,7 +757,7 @@ def test__process_response_partial_no_range(self): # Make sure the upload is valid before the failure. assert not upload.invalid with pytest.raises(common.InvalidResponse) as exc_info: - upload._process_response(response, None) + upload._process_resumable_response(response, None) # Make sure the upload is invalid after the failure. assert upload.invalid @@ -767,7 +767,7 @@ def test__process_response_partial_no_range(self): assert len(error.args) == 2 assert error.args[1] == "range" - def test__process_response_partial_bad_range(self): + def test__process_resumable_response_partial_bad_range(self): upload = _upload.ResumableUpload(RESUMABLE_URL, ONE_MB) _fix_up_virtual(upload) @@ -778,7 +778,7 @@ def test__process_response_partial_bad_range(self): status_code=http.client.PERMANENT_REDIRECT, headers=headers ) with pytest.raises(common.InvalidResponse) as exc_info: - upload._process_response(response, 81) + upload._process_resumable_response(response, 81) # Check the error response. error = exc_info.value @@ -788,7 +788,7 @@ def test__process_response_partial_bad_range(self): # Make sure the upload is invalid after the failure. assert upload.invalid - def test__process_response_partial(self): + def test__process_resumable_response_partial(self): upload = _upload.ResumableUpload(RESUMABLE_URL, ONE_MB) _fix_up_virtual(upload) @@ -798,7 +798,7 @@ def test__process_response_partial(self): response = _make_response( status_code=http.client.PERMANENT_REDIRECT, headers=headers ) - ret_val = upload._process_response(response, 172) + ret_val = upload._process_resumable_response(response, 172) assert ret_val is None # Check status after. assert upload._bytes_uploaded == 172 diff --git a/tests/unit/test_common.py b/tests/unit/test_common.py index 1ee4b34a..a8572bea 100644 --- a/tests/unit/test_common.py +++ b/tests/unit/test_common.py @@ -13,7 +13,7 @@ # limitations under the License. import mock -import pytest +import pytest # type: ignore from google.resumable_media import common diff --git a/tests_async/system/requests/conftest.py b/tests_async/system/requests/conftest.py index f7513d3e..81c39df2 100644 --- a/tests_async/system/requests/conftest.py +++ b/tests_async/system/requests/conftest.py @@ -15,9 +15,9 @@ from tests.system import utils -from google.auth._default_async import default_async -import google.auth.transport._aiohttp_requests as tr_requests -import pytest +from google.auth._default_async import default_async # type: ignore +import google.auth.transport._aiohttp_requests as tr_requests # type: ignore +import pytest # type: ignore async def ensure_bucket(transport): diff --git a/tests_async/system/requests/test_download.py b/tests_async/system/requests/test_download.py index ae9ec215..483d8598 100644 --- a/tests_async/system/requests/test_download.py +++ b/tests_async/system/requests/test_download.py @@ -20,10 +20,10 @@ import os import asyncio -from google.auth._default_async import default_async -import google.auth.transport._aiohttp_requests as tr_requests -import multidict -import pytest +from google.auth._default_async import default_async # type: ignore +import google.auth.transport._aiohttp_requests as tr_requests # type: ignore +import multidict # type: ignore +import pytest # type: ignore import google._async_resumable_media.requests as resumable_requests from google.resumable_media import _helpers diff --git a/tests_async/system/requests/test_upload.py b/tests_async/system/requests/test_upload.py index 455fe4db..fb8ba51a 100644 --- a/tests_async/system/requests/test_upload.py +++ b/tests_async/system/requests/test_upload.py @@ -21,7 +21,7 @@ import asyncio import mock -import pytest +import pytest # type: ignore from google.resumable_media import common from google import _async_resumable_media diff --git a/tests_async/unit/requests/test__helpers.py b/tests_async/unit/requests/test__helpers.py index 6e412b12..333c2dec 100644 --- a/tests_async/unit/requests/test__helpers.py +++ b/tests_async/unit/requests/test__helpers.py @@ -15,9 +15,9 @@ import http.client import io -import aiohttp +import aiohttp # type: ignore import mock -import pytest +import pytest # type: ignore from google._async_resumable_media.requests import _request_helpers as _helpers diff --git a/tests_async/unit/requests/test_download.py b/tests_async/unit/requests/test_download.py index 60c3da5e..9892206b 100644 --- a/tests_async/unit/requests/test_download.py +++ b/tests_async/unit/requests/test_download.py @@ -15,9 +15,9 @@ import http.client import io -import aiohttp +import aiohttp # type: ignore import mock -import pytest +import pytest # type: ignore from google.resumable_media import common diff --git a/tests_async/unit/requests/test_upload.py b/tests_async/unit/requests/test_upload.py index c59fa18a..e9a0eb1a 100644 --- a/tests_async/unit/requests/test_upload.py +++ b/tests_async/unit/requests/test_upload.py @@ -12,13 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. -import aiohttp import http.client import io import json -import pytest -import mock +import aiohttp # type: ignore +import mock # type: ignore +import pytest # type: ignore import google._async_resumable_media.requests.upload as upload_mod from tests.unit.requests import test_upload as sync_test diff --git a/tests_async/unit/test__download.py b/tests_async/unit/test__download.py index 87e30ce8..8dfd1304 100644 --- a/tests_async/unit/test__download.py +++ b/tests_async/unit/test__download.py @@ -15,9 +15,9 @@ import http.client import io -import google.auth.transport._aiohttp_requests as aiohttp_requests +import google.auth.transport._aiohttp_requests as aiohttp_requests # type: ignore import mock -import pytest +import pytest # type: ignore from google._async_resumable_media import _download from google.resumable_media import common diff --git a/tests_async/unit/test__helpers.py b/tests_async/unit/test__helpers.py index 9617d57e..b95bb5a0 100644 --- a/tests_async/unit/test__helpers.py +++ b/tests_async/unit/test__helpers.py @@ -15,7 +15,7 @@ import http.client import mock -import pytest +import pytest # type: ignore from google._async_resumable_media import _helpers from google.resumable_media import common diff --git a/tests_async/unit/test__upload.py b/tests_async/unit/test__upload.py index b4b18bc0..d76bdc6c 100644 --- a/tests_async/unit/test__upload.py +++ b/tests_async/unit/test__upload.py @@ -17,7 +17,7 @@ import sys import mock -import pytest +import pytest # type: ignore from google._async_resumable_media import _upload from google.resumable_media import common @@ -705,7 +705,7 @@ def test__make_invalid(self): assert upload.invalid @pytest.mark.asyncio - async def test__process_response_bad_status(self): + async def test__process_resumable_response_bad_status(self): upload = _upload.ResumableUpload(sync_test.RESUMABLE_URL, sync_test.ONE_MB) _fix_up_virtual(upload) @@ -713,7 +713,7 @@ async def test__process_response_bad_status(self): assert not upload.invalid response = _make_response(status_code=http.client.NOT_FOUND) with pytest.raises(common.InvalidResponse) as exc_info: - await upload._process_response(response, None) + await upload._process_resumable_response(response, None) error = exc_info.value assert error.response is response @@ -725,7 +725,7 @@ async def test__process_response_bad_status(self): assert upload.invalid @pytest.mark.asyncio - async def test__process_response_success(self): + async def test__process_resumable_response_success(self): upload = _upload.ResumableUpload(sync_test.RESUMABLE_URL, sync_test.ONE_MB) _fix_up_virtual(upload) @@ -744,14 +744,14 @@ async def test__process_response_success(self): status_code=http.client.OK, spec=["content", "status_code"], ) - ret_val = await upload._process_response(response, bytes_sent) + ret_val = await upload._process_resumable_response(response, bytes_sent) assert ret_val is None # Check status after. assert upload._bytes_uploaded == total_bytes assert upload._finished @pytest.mark.asyncio - async def test__process_response_partial_no_range(self): + async def test__process_resumable_response_partial_no_range(self): upload = _upload.ResumableUpload(sync_test.RESUMABLE_URL, sync_test.ONE_MB) _fix_up_virtual(upload) @@ -759,7 +759,7 @@ async def test__process_response_partial_no_range(self): # Make sure the upload is valid before the failure. assert not upload.invalid with pytest.raises(common.InvalidResponse) as exc_info: - await upload._process_response(response, None) + await upload._process_resumable_response(response, None) # Make sure the upload is invalid after the failure. assert upload.invalid @@ -770,7 +770,7 @@ async def test__process_response_partial_no_range(self): assert error.args[1] == "range" @pytest.mark.asyncio - async def test__process_response_partial_bad_range(self): + async def test__process_resumable_response_partial_bad_range(self): upload = _upload.ResumableUpload(sync_test.RESUMABLE_URL, sync_test.ONE_MB) _fix_up_virtual(upload) @@ -781,7 +781,7 @@ async def test__process_response_partial_bad_range(self): status_code=http.client.PERMANENT_REDIRECT, headers=headers ) with pytest.raises(common.InvalidResponse) as exc_info: - await upload._process_response(response, 81) + await upload._process_resumable_response(response, 81) # Check the error response. error = exc_info.value @@ -792,7 +792,7 @@ async def test__process_response_partial_bad_range(self): assert upload.invalid @pytest.mark.asyncio - async def test__process_response_partial(self): + async def test__process_resumable_response_partial(self): upload = _upload.ResumableUpload(sync_test.RESUMABLE_URL, sync_test.ONE_MB) _fix_up_virtual(upload) @@ -802,7 +802,7 @@ async def test__process_response_partial(self): response = _make_response( status_code=http.client.PERMANENT_REDIRECT, headers=headers ) - ret_val = await upload._process_response(response, 172) + ret_val = await upload._process_resumable_response(response, 172) assert ret_val is None # Check status after. assert upload._bytes_uploaded == 172