Skip to content
This repository was archived by the owner on Mar 31, 2026. It is now read-only.

Commit accac90

Browse files
committed
feat: add get_object method for async grpc client
1 parent 2ef6339 commit accac90

2 files changed

Lines changed: 137 additions & 0 deletions

File tree

google/cloud/storage/asyncio/async_grpc_client.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,66 @@ async def delete_object(
158158
**kwargs,
159159
)
160160
await self._grpc_client.delete_object(request=request)
161+
162+
async def get_object(
163+
self,
164+
bucket_name,
165+
object_name,
166+
generation=None,
167+
if_generation_match=None,
168+
if_generation_not_match=None,
169+
if_metageneration_match=None,
170+
if_metageneration_not_match=None,
171+
soft_deleted=None,
172+
**kwargs,
173+
):
174+
"""Retrieves an object's metadata.
175+
176+
In the gRPC API, this is performed by the GetObject RPC, which
177+
returns the object resource (metadata) without the object's data.
178+
179+
:type bucket_name: str
180+
:param bucket_name: The name of the bucket in which the object resides.
181+
182+
:type object_name: str
183+
:param object_name: The name of the object.
184+
185+
:type generation: int
186+
:param generation:
187+
(Optional) If present, selects a specific generation of an object.
188+
189+
:type if_generation_match: int
190+
:param if_generation_match: (Optional) Precondition for object generation match.
191+
192+
:type if_generation_not_match: int
193+
:param if_generation_not_match: (Optional) Precondition for object generation mismatch.
194+
195+
:type if_metageneration_match: int
196+
:param if_metageneration_match: (Optional) Precondition for metageneration match.
197+
198+
:type if_metageneration_not_match: int
199+
:param if_metageneration_not_match: (Optional) Precondition for metageneration mismatch.
200+
201+
:type soft_deleted: bool
202+
:param soft_deleted:
203+
(Optional) If True, return the soft-deleted version of this object.
204+
205+
:rtype: :class:`google.cloud._storage_v2.types.Object`
206+
:returns: The object metadata resource.
207+
"""
208+
bucket_path = f"projects/_/buckets/{bucket_name}"
209+
210+
request = storage_v2.GetObjectRequest(
211+
bucket=bucket_path,
212+
object=object_name,
213+
generation=generation,
214+
if_generation_match=if_generation_match,
215+
if_generation_not_match=if_generation_not_match,
216+
if_metageneration_match=if_metageneration_match,
217+
if_metageneration_not_match=if_metageneration_not_match,
218+
soft_deleted=soft_deleted if soft_deleted is not None else False,
219+
**kwargs,
220+
)
221+
222+
# Calls the underlying GAPIC StorageAsyncClient.get_object method
223+
return await self._grpc_client.get_object(request=request)

tests/unit/asyncio/test_async_grpc_client.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,3 +254,77 @@ async def test_delete_object(self, mock_async_storage_client):
254254
assert request.if_generation_not_match == if_generation_not_match
255255
assert request.if_metageneration_match == if_metageneration_match
256256
assert request.if_metageneration_not_match == if_metageneration_not_match
257+
258+
@mock.patch("google.cloud._storage_v2.StorageAsyncClient")
259+
@pytest.mark.asyncio
260+
async def test_get_object(self, mock_async_storage_client):
261+
# Arrange
262+
mock_transport_cls = mock.MagicMock()
263+
mock_async_storage_client.get_transport_class.return_value = mock_transport_cls
264+
mock_gapic_client = mock.AsyncMock()
265+
mock_async_storage_client.return_value = mock_gapic_client
266+
267+
client = async_grpc_client.AsyncGrpcClient(
268+
credentials=_make_credentials(spec=AnonymousCredentials)
269+
)
270+
271+
bucket_name = "bucket"
272+
object_name = "object"
273+
274+
# Act
275+
await client.get_object(
276+
bucket_name,
277+
object_name,
278+
)
279+
280+
# Assert
281+
call_args, call_kwargs = mock_gapic_client.get_object.call_args
282+
request = call_kwargs["request"]
283+
assert request.bucket == "projects/_/buckets/bucket"
284+
assert request.object == "object"
285+
286+
@mock.patch("google.cloud._storage_v2.StorageAsyncClient")
287+
@pytest.mark.asyncio
288+
async def test_get_object_with_all_parameters(self, mock_async_storage_client):
289+
# Arrange
290+
mock_transport_cls = mock.MagicMock()
291+
mock_async_storage_client.get_transport_class.return_value = mock_transport_cls
292+
mock_gapic_client = mock.AsyncMock()
293+
mock_async_storage_client.return_value = mock_gapic_client
294+
295+
client = async_grpc_client.AsyncGrpcClient(
296+
credentials=_make_credentials(spec=AnonymousCredentials)
297+
)
298+
299+
bucket_name = "bucket"
300+
object_name = "object"
301+
generation = 123
302+
if_generation_match = 456
303+
if_generation_not_match = 789
304+
if_metageneration_match = 111
305+
if_metageneration_not_match = 222
306+
soft_deleted = True
307+
308+
# Act
309+
await client.get_object(
310+
bucket_name,
311+
object_name,
312+
generation=generation,
313+
if_generation_match=if_generation_match,
314+
if_generation_not_match=if_generation_not_match,
315+
if_metageneration_match=if_metageneration_match,
316+
if_metageneration_not_match=if_metageneration_not_match,
317+
soft_deleted=soft_deleted,
318+
)
319+
320+
# Assert
321+
call_args, call_kwargs = mock_gapic_client.get_object.call_args
322+
request = call_kwargs["request"]
323+
assert request.bucket == "projects/_/buckets/bucket"
324+
assert request.object == "object"
325+
assert request.generation == generation
326+
assert request.if_generation_match == if_generation_match
327+
assert request.if_generation_not_match == if_generation_not_match
328+
assert request.if_metageneration_match == if_metageneration_match
329+
assert request.if_metageneration_not_match == if_metageneration_not_match
330+
assert request.soft_deleted is True

0 commit comments

Comments
 (0)