Skip to content

Commit c31a516

Browse files
authored
feat(experimental): Implement __init__ method for _AsyncReadObjectStream (#1548)
* feat(experimental): Implement `__init__` method for _AsyncReadObjectStream (#1548)
1 parent 3c8a21d commit c31a516

File tree

2 files changed

+45
-51
lines changed

2 files changed

+45
-51
lines changed

google/cloud/storage/_experimental/asyncio/async_read_object_stream.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
from google.cloud.storage._experimental.asyncio.async_abstract_object_stream import (
2929
_AsyncAbstractObjectStream,
3030
)
31+
from google.cloud.storage._experimental.asyncio.bidi_async import AsyncBidiRpc
3132

3233

3334
class _AsyncReadObjectStream(_AsyncAbstractObjectStream):
@@ -36,7 +37,7 @@ class _AsyncReadObjectStream(_AsyncAbstractObjectStream):
3637
This class provides a unix socket-like interface to a GCS ``Object``, with
3738
methods like ``open``, ``close``, ``send``, and ``recv``.
3839
39-
:type client: :class:`~google.cloud.storage.asyncio.AsyncGrpcClient.grpc_client`
40+
:type client: :class:`~google.cloud.storage._experimental.asyncio.async_grpc_client.AsyncGrpcClient.grpc_client`
4041
:param client: async grpc client to use for making API requests.
4142
4243
:type bucket_name: str
@@ -77,6 +78,21 @@ def __init__(
7778
self.client: AsyncGrpcClient.grpc_client = client
7879
self.read_handle: Optional[bytes] = read_handle
7980

81+
self._full_bucket_name = f"projects/_/buckets/{self.bucket_name}"
82+
83+
self.rpc = self.client._client._transport._wrapped_methods[
84+
self.client._client._transport.bidi_read_object
85+
]
86+
first_bidi_read_req = _storage_v2.BidiReadObjectRequest(
87+
read_object_spec=_storage_v2.BidiReadObjectSpec(
88+
bucket=self._full_bucket_name, object=object_name
89+
),
90+
)
91+
self.metadata = (("x-goog-request-params", f"bucket={self._full_bucket_name}"),)
92+
self.socket_like_rpc = AsyncBidiRpc(
93+
self.rpc, initial_request=first_bidi_read_req, metadata=self.metadata
94+
)
95+
8096
async def open(self) -> None:
8197
pass
8298

tests/unit/asyncio/test_async_read_object_stream.py

Lines changed: 28 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -14,73 +14,51 @@
1414

1515
import pytest
1616
from unittest import mock
17+
from google.cloud import _storage_v2
1718

18-
from google.cloud.storage._experimental.asyncio.async_abstract_object_stream import (
19-
_AsyncAbstractObjectStream,
20-
)
2119
from google.cloud.storage._experimental.asyncio.async_read_object_stream import (
2220
_AsyncReadObjectStream,
2321
)
2422

2523

26-
def test_inheritance():
27-
"""Test that _AsyncReadObjectStream inherits from _AsyncAbstractObjectStream."""
28-
assert issubclass(_AsyncReadObjectStream, _AsyncAbstractObjectStream)
29-
30-
31-
def test_init():
32-
"""Test the constructor of _AsyncReadObjectStream."""
33-
mock_client = mock.Mock(name="client")
24+
@mock.patch(
25+
"google.cloud.storage._experimental.asyncio.async_read_object_stream.AsyncBidiRpc"
26+
)
27+
@mock.patch(
28+
"google.cloud.storage._experimental.asyncio.async_grpc_client.AsyncGrpcClient.grpc_client"
29+
)
30+
def test_init_with_bucket_object_generation(mock_client, mock_async_bidi_rpc):
31+
# initialize with bucket, object_name and generation number. & client.
3432
bucket_name = "test-bucket"
3533
object_name = "test-object"
36-
generation = 12345
37-
read_handle = "some-handle"
34+
generation_number = 12345
35+
mock_client._client._transport.bidi_read_object = "bidi_read_object_rpc"
36+
mock_client._client._transport._wrapped_methods = {
37+
"bidi_read_object_rpc": mock.sentinel.A
38+
}
3839

39-
# Test with all parameters
40-
stream = _AsyncReadObjectStream(
41-
mock_client,
40+
read_obj_stream = _AsyncReadObjectStream(
41+
client=mock_client,
4242
bucket_name=bucket_name,
4343
object_name=object_name,
44-
generation_number=generation,
45-
read_handle=read_handle,
44+
generation_number=generation_number,
4645
)
47-
48-
assert stream.client is mock_client
49-
assert stream.bucket_name == bucket_name
50-
assert stream.object_name == object_name
51-
assert stream.generation_number == generation
52-
assert stream.read_handle == read_handle
53-
54-
# Test with default parameters
55-
stream_defaults = _AsyncReadObjectStream(
56-
mock_client, bucket_name=bucket_name, object_name=object_name
46+
full_bucket_name = f"projects/_/buckets/{bucket_name}"
47+
first_bidi_read_req = _storage_v2.BidiReadObjectRequest(
48+
read_object_spec=_storage_v2.BidiReadObjectSpec(
49+
bucket=full_bucket_name, object=object_name
50+
),
51+
)
52+
mock_async_bidi_rpc.assert_called_once_with(
53+
mock.sentinel.A,
54+
initial_request=first_bidi_read_req,
55+
metadata=(("x-goog-request-params", f"bucket={full_bucket_name}"),),
5756
)
58-
assert stream_defaults.client is mock_client
59-
assert stream_defaults.bucket_name is bucket_name
60-
assert stream_defaults.object_name is object_name
61-
assert stream_defaults.generation_number is None
62-
assert stream_defaults.read_handle is None
57+
assert read_obj_stream.socket_like_rpc is mock_async_bidi_rpc.return_value
6358

6459

6560
def test_init_with_invalid_parameters():
6661
"""Test the constructor of _AsyncReadObjectStream with invalid params."""
6762

6863
with pytest.raises(ValueError):
6964
_AsyncReadObjectStream(None, bucket_name=None, object_name=None)
70-
71-
72-
@pytest.mark.asyncio
73-
async def test_async_methods_are_awaitable():
74-
"""Test that the async methods exist and are awaitable."""
75-
mock_client = mock.Mock(name="client")
76-
stream = _AsyncReadObjectStream(mock_client, "bucket", "object")
77-
78-
# These methods are currently empty, but we can test they are awaitable
79-
# and don't raise exceptions.
80-
try:
81-
await stream.open()
82-
await stream.close()
83-
await stream.send(mock.Mock())
84-
await stream.recv()
85-
except Exception as e:
86-
pytest.fail(f"Async methods should be awaitable without errors. Raised: {e}")

0 commit comments

Comments
 (0)