From 224a2e9bcd15f88093cc7e95c0d4462b938e4e2e Mon Sep 17 00:00:00 2001 From: Tim Holm Date: Wed, 2 Nov 2022 16:32:34 +1100 Subject: [PATCH] feat: SDK improvements. --- nitric/api/events.py | 3 +-- nitric/api/storage.py | 18 +++++++++++------- nitric/resources/base.py | 10 +++++----- nitric/resources/buckets.py | 8 ++++---- nitric/resources/collections.py | 8 ++++---- nitric/resources/queues.py | 8 ++++---- nitric/resources/secrets.py | 8 ++++---- nitric/resources/topics.py | 8 ++++---- tests/api/test_events.py | 2 +- tests/resources/test_buckets.py | 10 +++++----- tests/resources/test_collections.py | 10 +++++----- tests/resources/test_queues.py | 6 +++--- tests/resources/test_secrets.py | 4 ++-- tests/resources/test_topics.py | 2 +- 14 files changed, 54 insertions(+), 51 deletions(-) diff --git a/nitric/api/events.py b/nitric/api/events.py index d216f07..4bf2dd2 100644 --- a/nitric/api/events.py +++ b/nitric/api/events.py @@ -67,8 +67,7 @@ async def publish( event = Event() if isinstance(event, dict): - # TODO: handle events that are just a payload - event = Event(**event) + event = Event(payload=event) try: response = await self._events._stub.publish( diff --git a/nitric/api/storage.py b/nitric/api/storage.py index 253c145..49ecc7d 100644 --- a/nitric/api/storage.py +++ b/nitric/api/storage.py @@ -20,8 +20,6 @@ from typing import List from grpclib import GRPCError -from nitric.api.storage import File - from nitric.api.exception import exception_from_grpc_error, InvalidArgumentException from nitric.utils import new_default_channel from nitricapi.nitric.storage.v1 import StorageServiceStub, StoragePreSignUrlRequestOperation, StorageWriteRequest, \ @@ -62,10 +60,12 @@ def file(self, key: str): """Return a reference to a file in this bucket.""" return File(_storage=self._storage, _bucket=self.name, key=key) - async def files(self) -> List[File]: - resp = await self._storage._storage_stub.list_files(storage_list_files_request=StorageListFilesRequest(bucket_name=self.name)) + async def files(self): + resp = await self._storage._storage_stub.list_files( + storage_list_files_request=StorageListFilesRequest(bucket_name=self.name)) return [self.file(f.key) for f in resp.files] + class FileMode(Enum): """Definition of available operation modes for file signed URLs.""" @@ -81,6 +81,7 @@ def to_request_operation(self) -> StoragePreSignUrlRequestOperation: else: raise InvalidArgumentException("Invalid FileMode") + @dataclass(frozen=True, order=True) class File(object): """A reference to a file in a bucket, used to perform operations on that file.""" @@ -96,14 +97,16 @@ async def write(self, body: bytes): Will create the file if it doesn't already exist. """ try: - await self._storage._storage_stub.write(storage_write_request=StorageWriteRequest(bucket_name=self._bucket, key=self.key, body=body)) + await self._storage._storage_stub.write( + storage_write_request=StorageWriteRequest(bucket_name=self._bucket, key=self.key, body=body)) except GRPCError as grpc_err: raise exception_from_grpc_error(grpc_err) async def read(self) -> bytes: """Read this files contents from the bucket.""" try: - response = await self._storage._storage_stub.read(storage_read_request=StorageReadRequest(bucket_name=self._bucket, key=self.key)) + response = await self._storage._storage_stub.read( + storage_read_request=StorageReadRequest(bucket_name=self._bucket, key=self.key)) return response.body except GRPCError as grpc_err: raise exception_from_grpc_error(grpc_err) @@ -111,7 +114,8 @@ async def read(self) -> bytes: async def delete(self): """Delete this file from the bucket.""" try: - await self._storage._storage_stub.delete(storage_delete_request=StorageDeleteRequest(bucket_name=self._bucket, key=self.key)) + await self._storage._storage_stub.delete( + storage_delete_request=StorageDeleteRequest(bucket_name=self._bucket, key=self.key)) except GRPCError as grpc_err: raise exception_from_grpc_error(grpc_err) diff --git a/nitric/resources/base.py b/nitric/resources/base.py index ab0c1a7..9117ba1 100644 --- a/nitric/resources/base.py +++ b/nitric/resources/base.py @@ -76,16 +76,16 @@ def _to_resource(self) -> Resource: pass @abstractmethod - def _perms_to_actions(self, permissions: List[str]) -> List[Action]: + def _perms_to_actions(self, *args: str) -> List[Action]: pass - async def _register_policy_async(self, permissions: List[str]): + async def _register_policy_async(self, *args: str): # if self._reg is not None: # await asyncio.wait({self._reg}) policy = PolicyResource( principals=[Resource(type=ResourceType.Function)], - actions=self._perms_to_actions(permissions), + actions=self._perms_to_actions(*args), resources=[self._to_resource()], ) try: @@ -95,7 +95,7 @@ async def _register_policy_async(self, permissions: List[str]): except GRPCError as grpc_err: raise exception_from_grpc_error(grpc_err) - def _register_policy(self, permissions: List[str]): + def _register_policy(self, *args: str): loop = asyncio.get_event_loop() - loop.run_until_complete(self._register_policy_async(permissions)) + loop.run_until_complete(self._register_policy_async(*args)) diff --git a/nitric/resources/buckets.py b/nitric/resources/buckets.py index 4366bbb..d6db1d7 100644 --- a/nitric/resources/buckets.py +++ b/nitric/resources/buckets.py @@ -60,7 +60,7 @@ async def _register(self): except GRPCError as grpc_err: raise exception_from_grpc_error(grpc_err) - def _perms_to_actions(self, permissions: List[Union[BucketPermission, str]]) -> List[Action]: + def _perms_to_actions(self, *args: [Union[BucketPermission, str]]) -> List[Action]: permission_actions_map = { BucketPermission.reading: [Action.BucketFileGet, Action.BucketFileList], BucketPermission.writing: [Action.BucketFilePut], @@ -69,16 +69,16 @@ def _perms_to_actions(self, permissions: List[Union[BucketPermission, str]]) -> # convert strings to the enum value where needed perms = [ permission if isinstance(permission, BucketPermission) else BucketPermission[permission.lower()] - for permission in permissions + for permission in args ] return [action for perm in perms for action in permission_actions_map[perm]] def _to_resource(self) -> Resource: return Resource(name=self.name, type=ResourceType.Bucket) - def allow(self, permissions: List[Union[BucketPermission, str]]) -> BucketRef: + def allow(self, *args: Union[BucketPermission, str]) -> BucketRef: """Request the required permissions for this resource.""" - self._register_policy(permissions) + self._register_policy(*args) return Storage().bucket(self.name) diff --git a/nitric/resources/collections.py b/nitric/resources/collections.py index 07edbd0..744cd75 100644 --- a/nitric/resources/collections.py +++ b/nitric/resources/collections.py @@ -61,7 +61,7 @@ async def _register(self): def _to_resource(self) -> Resource: return Resource(name=self.name, type=ResourceType.Collection) - def _perms_to_actions(self, permissions: List[Union[CollectionPermission, str]]) -> List[Action]: + def _perms_to_actions(self, *args: Union[CollectionPermission, str]) -> List[Action]: permission_actions_map = { CollectionPermission.reading: [Action.CollectionDocumentRead, Action.CollectionQuery, Action.CollectionList], @@ -71,15 +71,15 @@ def _perms_to_actions(self, permissions: List[Union[CollectionPermission, str]]) # convert strings to the enum value where needed perms = [ permission if isinstance(permission, CollectionPermission) else CollectionPermission[permission.lower()] - for permission in permissions + for permission in args ] return [action for perm in perms for action in permission_actions_map[perm]] - def allow(self, permissions: List[Union[CollectionPermission, str]]) -> CollectionRef: + def allow(self, *args: Union[CollectionPermission, str]) -> CollectionRef: """Request the required permissions for this collection.""" # Ensure registration of the resource is complete before requesting permissions. - self._register_policy(permissions) + self._register_policy(*args) return Documents().collection(self.name) diff --git a/nitric/resources/queues.py b/nitric/resources/queues.py index 58e3e0e..15f1b7b 100644 --- a/nitric/resources/queues.py +++ b/nitric/resources/queues.py @@ -54,7 +54,7 @@ def __init__(self, name: str): def _to_resource(self) -> Resource: return Resource(name=self.name, type=ResourceType.Queue) - def _perms_to_actions(self, permissions: List[Union[QueuePermission, str]]) -> List[Action]: + def _perms_to_actions(self, *args: Union[QueuePermission, str]) -> List[Action]: permission_actions_map = { QueuePermission.sending: [Action.QueueSend, Action.QueueList, Action.QueueDetail], QueuePermission.receiving: [Action.QueueReceive, Action.QueueList, Action.QueueDetail], @@ -62,7 +62,7 @@ def _perms_to_actions(self, permissions: List[Union[QueuePermission, str]]) -> L # convert strings to the enum value where needed perms = [ permission if isinstance(permission, QueuePermission) else QueuePermission[permission.lower()] - for permission in permissions + for permission in args ] return [action for perm in perms for action in permission_actions_map[perm]] @@ -74,10 +74,10 @@ async def _register(self): except GRPCError as grpc_err: raise exception_from_grpc_error(grpc_err) - def allow(self, permissions: List[Union[QueuePermission, str]]) -> QueueRef: + def allow(self, *args: Union[QueuePermission, str]) -> QueueRef: """Request the required permissions for this queue.""" # Ensure registration of the resource is complete before requesting permissions. - self._register_policy(permissions) + self._register_policy(*args) return Queues().queue(self.name) diff --git a/nitric/resources/secrets.py b/nitric/resources/secrets.py index 30033da..fb7c19e 100644 --- a/nitric/resources/secrets.py +++ b/nitric/resources/secrets.py @@ -65,7 +65,7 @@ async def _register(self): except GRPCError as grpc_err: raise exception_from_grpc_error(grpc_err) - def _perms_to_actions(self, permissions: List[Union[SecretPermission, str]]) -> List[Action]: + def _perms_to_actions(self, *args: Union[SecretPermission, str]) -> List[Action]: permissions_actions_map = { SecretPermission.accessing: [Action.SecretAccess], SecretPermission.putting: [Action.SecretPut], @@ -73,15 +73,15 @@ def _perms_to_actions(self, permissions: List[Union[SecretPermission, str]]) -> # convert strings to the enum value where needed perms = [ permission if isinstance(permission, SecretPermission) else SecretPermission[permission.lower()] - for permission in permissions + for permission in args ] return [action for perm in perms for action in permissions_actions_map[perm]] - def allow(self, permissions: List[Union[SecretPermission, str]]) -> SecretContainerRef: + def allow(self, *args: Union[SecretPermission, str]) -> SecretContainerRef: """Request the specified permissions to this resource.""" - self._register_policy(permissions) + self._register_policy(*args) return Secrets().secret(self.name) diff --git a/nitric/resources/topics.py b/nitric/resources/topics.py index 18def4b..5e3e793 100644 --- a/nitric/resources/topics.py +++ b/nitric/resources/topics.py @@ -62,20 +62,20 @@ async def _register(self): def _to_resource(self) -> Resource: return Resource(name=self.name, type=ResourceType.Topic) - def _perms_to_actions(self, permissions: List[Union[TopicPermission, str]]) -> List[Action]: + def _perms_to_actions(self, *args: Union[TopicPermission, str]) -> List[Action]: _permMap = {TopicPermission.publishing: [Action.TopicEventPublish]} # convert strings to the enum value where needed perms = [ permission if isinstance(permission, TopicPermission) else TopicPermission[permission.lower()] - for permission in permissions + for permission in args ] return [action for perm in perms for action in _permMap[perm]] - def allow(self, permissions: List[Union[TopicPermission, str]]) -> TopicRef: + def allow(self, *args: Union[TopicPermission, str]) -> TopicRef: """Request the specified permissions to this resource.""" - self._register_policy(permissions) + self._register_policy(*args) return Events().topic(self.name) diff --git a/tests/api/test_events.py b/tests/api/test_events.py index 714810c..603c88c 100644 --- a/tests/api/test_events.py +++ b/tests/api/test_events.py @@ -72,7 +72,7 @@ async def test_publish_dict(self): with patch("nitricapi.nitric.event.v1.EventServiceStub.publish", mock_publish): topic = Events().topic("test-topic") - await topic.publish({"id": "123", "payload": payload}) + await topic.publish(Event(id="123", payload=payload)) mock_publish.assert_called_once_with( event_publish_request=EventPublishRequest( diff --git a/tests/resources/test_buckets.py b/tests/resources/test_buckets.py index 4f77603..b1bd59a 100644 --- a/tests/resources/test_buckets.py +++ b/tests/resources/test_buckets.py @@ -37,7 +37,7 @@ def test_create_allow_writing(self): mock_declare.return_value = mock_response with patch("nitricapi.nitric.resource.v1.ResourceServiceStub.declare", mock_declare): - bucket("test-bucket").allow(["writing"]) + bucket("test-bucket").allow("writing") # Check expected values were passed to Stub mock_declare.assert_called_with(resource_declare_request=ResourceDeclareRequest( @@ -55,7 +55,7 @@ def test_create_allow_reading(self): mock_declare.return_value = mock_response with patch("nitricapi.nitric.resource.v1.ResourceServiceStub.declare", mock_declare): - bucket("test-bucket").allow(["reading"]) + bucket("test-bucket").allow("reading") # Check expected values were passed to Stub mock_declare.assert_called_with(resource_declare_request=ResourceDeclareRequest( @@ -73,7 +73,7 @@ def test_create_allow_deleting(self): mock_declare.return_value = mock_response with patch("nitricapi.nitric.resource.v1.ResourceServiceStub.declare", mock_declare): - bucket("test-bucket").allow(["deleting"]) + bucket("test-bucket").allow("deleting") # Check expected values were passed to Stub mock_declare.assert_called_with(resource_declare_request=ResourceDeclareRequest( @@ -91,7 +91,7 @@ def test_create_allow_all(self): mock_declare.return_value = mock_response with patch("nitricapi.nitric.resource.v1.ResourceServiceStub.declare", mock_declare): - bucket("test-bucket").allow(["deleting", "reading", "writing"]) + bucket("test-bucket").allow("deleting", "reading", "writing") # Check expected values were passed to Stub mock_declare.assert_called_with(resource_declare_request=ResourceDeclareRequest( @@ -114,7 +114,7 @@ def test_create_allow_all_reversed_policy(self): mock_declare.return_value = mock_response with patch("nitricapi.nitric.resource.v1.ResourceServiceStub.declare", mock_declare): - bucket("test-bucket").allow(["writing", "reading", "deleting"]) + bucket("test-bucket").allow("writing", "reading", "deleting") # Check expected values were passed to Stub mock_declare.assert_called_with(resource_declare_request=ResourceDeclareRequest( diff --git a/tests/resources/test_collections.py b/tests/resources/test_collections.py index fe12180..3b89a57 100644 --- a/tests/resources/test_collections.py +++ b/tests/resources/test_collections.py @@ -40,7 +40,7 @@ def test_create_allow_writing(self): mock_declare.return_value = mock_response with patch("nitricapi.nitric.resource.v1.ResourceServiceStub.declare", mock_declare): - collection("test-collection").allow(["writing"]) + collection("test-collection").allow("writing") # Check expected values were passed to Stub mock_declare.assert_called_with(resource_declare_request=ResourceDeclareRequest( @@ -61,7 +61,7 @@ def test_create_allow_reading(self): mock_declare.return_value = mock_response with patch("nitricapi.nitric.resource.v1.ResourceServiceStub.declare", mock_declare): - collection("test-collection").allow(["reading"]) + collection("test-collection").allow("reading") # Check expected values were passed to Stub mock_declare.assert_called_with(resource_declare_request=ResourceDeclareRequest( @@ -83,7 +83,7 @@ def test_create_allow_deleting(self): mock_declare.return_value = mock_response with patch("nitricapi.nitric.resource.v1.ResourceServiceStub.declare", mock_declare): - collection("test-collection").allow(["deleting"]) + collection("test-collection").allow("deleting") # Check expected values were passed to Stub mock_declare.assert_called_with(resource_declare_request=ResourceDeclareRequest( @@ -104,7 +104,7 @@ def test_create_allow_all(self): mock_declare.return_value = mock_response with patch("nitricapi.nitric.resource.v1.ResourceServiceStub.declare", mock_declare): - collection("test-collection").allow(["deleting", "reading", "writing"]) + collection("test-collection").allow("deleting", "reading", "writing") # Check expected values were passed to Stub mock_declare.assert_called_with(resource_declare_request=ResourceDeclareRequest( @@ -130,7 +130,7 @@ def test_create_allow_all_reversed_policy(self): mock_declare.return_value = mock_response with patch("nitricapi.nitric.resource.v1.ResourceServiceStub.declare", mock_declare): - collection("test-collection").allow(["writing", "reading", "deleting"]) + collection("test-collection").allow("writing", "reading", "deleting") # Check expected values were passed to Stub mock_declare.assert_called_with(resource_declare_request=ResourceDeclareRequest( diff --git a/tests/resources/test_queues.py b/tests/resources/test_queues.py index cf61ae2..46ad0b5 100644 --- a/tests/resources/test_queues.py +++ b/tests/resources/test_queues.py @@ -35,7 +35,7 @@ def test_create_allow_sending(self): mock_declare.return_value = mock_response with patch("nitricapi.nitric.resource.v1.ResourceServiceStub.declare", mock_declare): - queue("test-queue").allow(["sending"]) + queue("test-queue").allow("sending") # Check expected values were passed to Stub mock_declare.assert_called_with(resource_declare_request=ResourceDeclareRequest( @@ -57,7 +57,7 @@ def test_create_allow_receiving(self): mock_declare.return_value = mock_response with patch("nitricapi.nitric.resource.v1.ResourceServiceStub.declare", mock_declare): - queue("test-queue").allow(["receiving"]) + queue("test-queue").allow("receiving") # Check expected values were passed to Stub mock_declare.assert_called_with(resource_declare_request=ResourceDeclareRequest( @@ -79,7 +79,7 @@ def test_create_allow_all(self): mock_declare.return_value = mock_response with patch("nitricapi.nitric.resource.v1.ResourceServiceStub.declare", mock_declare): - queue("test-queue").allow(["sending", "receiving"]) + queue("test-queue").allow("sending", "receiving") # Check expected values were passed to Stub mock_declare.assert_called_with(resource_declare_request=ResourceDeclareRequest( diff --git a/tests/resources/test_secrets.py b/tests/resources/test_secrets.py index cbe3e6b..b43e602 100644 --- a/tests/resources/test_secrets.py +++ b/tests/resources/test_secrets.py @@ -35,7 +35,7 @@ def test_allow_put(self): mock_declare.return_value = mock_response with patch("nitricapi.nitric.resource.v1.ResourceServiceStub.declare", mock_declare): - secret("test-secret").allow(["putting"]) + secret("test-secret").allow("putting") # Check expected values were passed to Stub mock_declare.assert_called_with(resource_declare_request=ResourceDeclareRequest( @@ -56,7 +56,7 @@ def test_allow_access(self): mock_declare.return_value = mock_response with patch("nitricapi.nitric.resource.v1.ResourceServiceStub.declare", mock_declare): - secret("test-secret").allow(["accessing"]) + secret("test-secret").allow("accessing") # Check expected values were passed to Stub mock_declare.assert_called_with(resource_declare_request=ResourceDeclareRequest( diff --git a/tests/resources/test_topics.py b/tests/resources/test_topics.py index 21f2f45..c8e490f 100644 --- a/tests/resources/test_topics.py +++ b/tests/resources/test_topics.py @@ -42,7 +42,7 @@ def test_create_allow_publishing(self): mock_declare.return_value = mock_response with patch("nitricapi.nitric.resource.v1.ResourceServiceStub.declare", mock_declare): - topic("test-topic").allow(["publishing"]) + topic("test-topic").allow("publishing") # Check expected values were passed to Stub mock_declare.assert_called_with(resource_declare_request=ResourceDeclareRequest(