From 15b1c1f3c081d7dc36d24af5cfa6e5f0b76eccad Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Mon, 13 May 2024 01:24:48 +0200 Subject: [PATCH] [#398] Replaced `GoogleDriveFile` response with `GoogleDriveFileSchema`. --- .../platypush/responses/google.drive.rst | 5 - docs/source/responses.rst | 1 - platypush/message/response/google/__init__.py | 0 platypush/message/response/google/drive.py | 23 ---- platypush/plugins/google/drive/__init__.py | 107 ++++++++---------- platypush/schemas/google/drive.py | 47 ++++++++ 6 files changed, 95 insertions(+), 88 deletions(-) delete mode 100644 docs/source/platypush/responses/google.drive.rst delete mode 100644 platypush/message/response/google/__init__.py delete mode 100644 platypush/message/response/google/drive.py create mode 100644 platypush/schemas/google/drive.py diff --git a/docs/source/platypush/responses/google.drive.rst b/docs/source/platypush/responses/google.drive.rst deleted file mode 100644 index f9abbacfd5..0000000000 --- a/docs/source/platypush/responses/google.drive.rst +++ /dev/null @@ -1,5 +0,0 @@ -``google.drive`` -=========================================== - -.. automodule:: platypush.message.response.google.drive - :members: diff --git a/docs/source/responses.rst b/docs/source/responses.rst index f9bd22585e..7b8fdeb42f 100644 --- a/docs/source/responses.rst +++ b/docs/source/responses.rst @@ -6,6 +6,5 @@ Responses :maxdepth: 1 :caption: Responses: - platypush/responses/google.drive.rst platypush/responses/printer.cups.rst platypush/responses/tensorflow.rst diff --git a/platypush/message/response/google/__init__.py b/platypush/message/response/google/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/platypush/message/response/google/drive.py b/platypush/message/response/google/drive.py deleted file mode 100644 index f164edf881..0000000000 --- a/platypush/message/response/google/drive.py +++ /dev/null @@ -1,23 +0,0 @@ -from typing import Optional - -from platypush.message import Mapping -from platypush.message.response import Response - - -class GoogleDriveResponse(Response): - pass - - -class GoogleDriveFile(Mapping): - # noinspection PyShadowingBuiltins - def __init__(self, - type: str, - id: str, - name: str, - mime_type: Optional[str] = None, - *args, **kwargs): - super().__init__(id=id, name=name, type=type, - mime_type=mime_type, *args, **kwargs) - - -# vim:sw=4:ts=4:et: diff --git a/platypush/plugins/google/drive/__init__.py b/platypush/plugins/google/drive/__init__.py index 0d53af6f2c..ff3d1504ee 100644 --- a/platypush/plugins/google/drive/__init__.py +++ b/platypush/plugins/google/drive/__init__.py @@ -4,7 +4,7 @@ from typing import Optional, List, Union from platypush.plugins import action from platypush.plugins.google import GooglePlugin -from platypush.message.response.google.drive import GoogleDriveFile +from platypush.schemas.google.drive import GoogleDriveFileSchema class GoogleDrivePlugin(GooglePlugin): @@ -63,16 +63,15 @@ class GoogleDrivePlugin(GooglePlugin): scopes = [ 'https://www.googleapis.com/auth/drive', 'https://www.googleapis.com/auth/drive.appfolder', - 'https://www.googleapis.com/auth/drive.photos.readonly', + 'https://www.googleapis.com/auth/drive.file', ] - def __init__(self, *args, **kwargs): - super().__init__(scopes=self.scopes, *args, **kwargs) + def __init__(self, **kwargs): + super().__init__(scopes=self.scopes, **kwargs) - def get_service(self, **_): + def get_service(self, *_, **__): return super().get_service(service='drive', version='v3') - # noinspection PyShadowingBuiltins @action def files( self, @@ -82,7 +81,7 @@ class GoogleDrivePlugin(GooglePlugin): drive_id: Optional[str] = None, spaces: Optional[Union[str, List[str]]] = None, order_by: Optional[Union[str, List[str]]] = None, - ) -> Union[GoogleDriveFile, List[GoogleDriveFile]]: + ) -> List[dict]: """ Get the list of files. @@ -117,8 +116,9 @@ class GoogleDrivePlugin(GooglePlugin): Attributes will be sorted in ascending order by default. You can change that by by appending "``desc``" separated by a space to the attribute you want in descending order - e.g. ``["folder", "createdTime desc", "modifiedTime desc"]``. - """ + :return: .. schema:: google.drive.GoogleDriveFileSchema(many=True) + """ service = self.get_service() page_token = None files = [] @@ -152,15 +152,7 @@ class GoogleDrivePlugin(GooglePlugin): page_token = results.get('nextPageToken') files.extend( - [ - GoogleDriveFile( - id=f.get('id'), - name=f.get('name'), - type=f.get('kind').split('#')[1], - mime_type=f.get('mimeType'), - ) - for f in results.get('files', []) - ] + GoogleDriveFileSchema().dump(results.get('files', []), many=True) ) if not page_token or (limit and len(files) >= limit): @@ -172,16 +164,13 @@ class GoogleDrivePlugin(GooglePlugin): def get(self, file_id: str): """ Get the information of a file on the Drive by file ID. + :param file_id: File ID. + :return: .. schema:: google.drive.GoogleDriveFileSchema """ service = self.get_service() file = service.files().get(fileId=file_id).execute() - return GoogleDriveFile( - type=file.get('kind').split('#')[1], - id=file.get('id'), - name=file.get('name'), - mime_type=file.get('mimeType'), - ) + return GoogleDriveFileSchema().dump(file) @action def upload( @@ -193,7 +182,7 @@ class GoogleDrivePlugin(GooglePlugin): parents: Optional[List[str]] = None, starred: bool = False, target_mime_type: Optional[str] = None, - ) -> GoogleDriveFile: + ) -> dict: """ Upload a file to Google Drive. @@ -208,8 +197,11 @@ class GoogleDrivePlugin(GooglePlugin): (use "``application/vnd.google-apps.document``). See `the official documentation `_ for a complete list of supported types. + :return: The uploaded file metadata. + + .. schema:: google.drive.GoogleDriveFileSchema + """ - # noinspection PyPackageRequirements from googleapiclient.http import MediaFileUpload path = os.path.abspath(os.path.expanduser(path)) @@ -232,12 +224,7 @@ class GoogleDrivePlugin(GooglePlugin): .execute() ) - return GoogleDriveFile( - type=file.get('kind').split('#')[1], - id=file.get('id'), - name=file.get('name'), - mime_type=file.get('mimeType'), - ) + return dict(GoogleDriveFileSchema().dump(file)) @action def download(self, file_id: str, path: str) -> str: @@ -248,7 +235,6 @@ class GoogleDrivePlugin(GooglePlugin): :param path: Path of the file to upload. :return: The local file path. """ - # noinspection PyPackageRequirements from googleapiclient.http import MediaIoBaseDownload service = self.get_service() @@ -268,6 +254,7 @@ class GoogleDrivePlugin(GooglePlugin): with open(path, 'wb') as f: f.write(fh.getbuffer().tobytes()) + return path @action @@ -278,7 +265,7 @@ class GoogleDrivePlugin(GooglePlugin): mime_type: Optional[str] = None, parents: Optional[List[str]] = None, starred: bool = False, - ) -> GoogleDriveFile: + ) -> dict: """ Create a file. @@ -287,6 +274,10 @@ class GoogleDrivePlugin(GooglePlugin): :param mime_type: File MIME type. :param parents: List of folder IDs that will contain the file (default: drive root). :param starred: If True then the file will be marked as starred. + :return: The created file metadata. + + .. schema:: google.drive.GoogleDriveFileSchema + """ metadata = { 'name': name, @@ -300,13 +291,7 @@ class GoogleDrivePlugin(GooglePlugin): service = self.get_service() file = service.files().create(body=metadata, fields='*').execute() - - return GoogleDriveFile( - type=file.get('kind').split('#')[1], - id=file.get('id'), - name=file.get('name'), - mime_type=file.get('mimeType'), - ) + return dict(GoogleDriveFileSchema().dump(file)) @action def update( @@ -319,7 +304,7 @@ class GoogleDrivePlugin(GooglePlugin): mime_type: Optional[str] = None, starred: Optional[bool] = None, trashed: Optional[bool] = None, - ) -> GoogleDriveFile: + ) -> dict: """ Update the metadata or the content of a file. @@ -331,6 +316,10 @@ class GoogleDrivePlugin(GooglePlugin): :param mime_type: Set the file MIME type. :param starred: Change the starred flag. :param trashed: Move/remove from trash. + :return: The updated file metadata. + + .. schema:: google.drive.GoogleDriveFileSchema + """ metadata = {} if name: @@ -348,40 +337,40 @@ class GoogleDrivePlugin(GooglePlugin): if trashed is not None: metadata['trashed'] = trashed - service = self.get_service() - file = ( - service.files().update(fileId=file_id, body=metadata, fields='*').execute() - ) - - return GoogleDriveFile( - type=file.get('kind').split('#')[1], - id=file.get('id'), - name=file.get('name'), - mime_type=file.get('mimeType'), + return dict( + GoogleDriveFileSchema().dump( + self.get_service() + .files() + .update(fileId=file_id, body=metadata, fields='*') + .execute() + ) ) @action def delete(self, file_id: str): """ Delete a file from Google Drive. + :param file_id: File ID. """ service = self.get_service() service.files().delete(fileId=file_id).execute() @action - def copy(self, file_id: str) -> GoogleDriveFile: + def copy(self, file_id: str) -> dict: """ Create a copy of a file. + :param file_id: File ID. + :return: The copied file metadata. + + .. schema:: google.drive.GoogleDriveFileSchema + """ - service = self.get_service() - file = service.files().copy(fileId=file_id).execute() - return GoogleDriveFile( - type=file.get('kind').split('#')[1], - id=file.get('id'), - name=file.get('name'), - mime_type=file.get('mimeType'), + return dict( + GoogleDriveFileSchema().dump( + self.get_service().files().copy(fileId=file_id).execute() + ) ) @action diff --git a/platypush/schemas/google/drive.py b/platypush/schemas/google/drive.py new file mode 100644 index 0000000000..53ae9aeb1b --- /dev/null +++ b/platypush/schemas/google/drive.py @@ -0,0 +1,47 @@ +from marshmallow import INCLUDE, fields, pre_dump +from marshmallow.schema import Schema + + +class GoogleDriveFileSchema(Schema): + """ + Schema for Google Drive files. + """ + + class Meta: # type: ignore + """ + Include unknown fields in the deserialized output. + """ + + unknown = INCLUDE + + id = fields.String( + required=True, + metadata={'description': 'File ID'}, + ) + + type = fields.String( + required=True, + metadata={ + 'description': 'File type', + 'example': 'file', + }, + ) + + name = fields.String( + required=True, + metadata={'description': 'File name'}, + ) + + mime_type = fields.String( + required=True, + metadata={ + 'description': 'File MIME type', + 'example': 'plain/text', + }, + ) + + @pre_dump + def parse_type(self, data, **_): + data['type'] = data.pop('kind').split('#')[-1] + data['mime_type'] = data.pop('mimeType') + return data