diff --git a/.github/workflows/python-tests.yml b/.github/workflows/python-tests.yml new file mode 100644 index 0000000..474ac79 --- /dev/null +++ b/.github/workflows/python-tests.yml @@ -0,0 +1,26 @@ +name: Python tests + +on: [push] + +jobs: + build: + + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + cache: 'pip' + + - name: Installing requirements + run: pip install -e '.[dev]' + + - name: Running tests + run: pytest diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index ffc81b4..0000000 --- a/.travis.yml +++ /dev/null @@ -1,14 +0,0 @@ -language: python -python: - - "3.6" - - "3.7" - - "3.8" -# command to install dependencies -install: - - pip install '.[dev]' -# command to run tests -script: - - pytest --cov=./ --cov-report=html - -after_success: - - codecov diff --git a/README.md b/README.md index a6022f6..19bbbe6 100644 --- a/README.md +++ b/README.md @@ -15,9 +15,8 @@ Library and cli to manage and interact with your Google Drive, sheets and docs 1. [License](#license) # Introduction -[![Build Status](https://travis-ci.org/eduardogr/google-drive-python.svg?branch=main)](https://travis-ci.org/github/eduardogr/google-drive-python) -[![codecov](https://codecov.io/gh/eduardogr/google-drive-python/branch/main/graph/badge.svg?token=E183Y3LLXX)](https://codecov.io/gh/eduardogr/google-drive-python) -[![Python](https://img.shields.io/badge/Python-v3.6%2B-blue)]() +![Build Status](https://github.com/eduardogr/google-drive-python/actions/workflows/python-tests.yml/badge.svg?event=push) +[![Python](https://img.shields.io/badge/Python-v3.9%2B-blue)]() [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md) [![GitHub license](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/eduardogr/google-drive-python/blob/main/LICENSE) diff --git a/docs/Makefile b/docs/Makefile deleted file mode 100644 index d0c3cbf..0000000 --- a/docs/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line, and also -# from the environment for the first two. -SPHINXOPTS ?= -SPHINXBUILD ?= sphinx-build -SOURCEDIR = source -BUILDDIR = build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/make.bat b/docs/make.bat deleted file mode 100644 index 6247f7e..0000000 --- a/docs/make.bat +++ /dev/null @@ -1,35 +0,0 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set SOURCEDIR=source -set BUILDDIR=build - -if "%1" == "" goto help - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.http://sphinx-doc.org/ - exit /b 1 -) - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% - -:end -popd diff --git a/docs/source/conf.py b/docs/source/conf.py deleted file mode 100644 index adc79d7..0000000 --- a/docs/source/conf.py +++ /dev/null @@ -1,54 +0,0 @@ -# Configuration file for the Sphinx documentation builder. -# -# This file only contains a selection of the most common options. For a full -# list see the documentation: -# https://www.sphinx-doc.org/en/master/usage/configuration.html - -# -- Path setup -------------------------------------------------------------- - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -# import os -# import sys -# sys.path.insert(0, os.path.abspath('.')) - - -# -- Project information ----------------------------------------------------- - -project = "google-drive" -copyright = "2020, Eduardo" -author = "Eduardo" - -# The full version, including alpha/beta/rc tags -release = "0.3.2" - - -# -- General configuration --------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ["_templates"] - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This pattern also affects html_static_path and html_extra_path. -exclude_patterns = [] - - -# -- Options for HTML output ------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -html_theme = "alabaster" - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ["_static"] diff --git a/docs/source/index.rst b/docs/source/index.rst deleted file mode 100644 index db03e55..0000000 --- a/docs/source/index.rst +++ /dev/null @@ -1,20 +0,0 @@ -.. google-drive documentation master file, created by - sphinx-quickstart on Sun Nov 22 22:18:43 2020. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Welcome to google-drive's documentation! -======================================== - -.. toctree:: - :maxdepth: 2 - :caption: Contents: - - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/googledrive/api.py b/googledrive/api.py index ed53384..f40f046 100644 --- a/googledrive/api.py +++ b/googledrive/api.py @@ -1,19 +1,14 @@ import pickle import os.path -import json from googleapiclient.discovery import build from googleapiclient.errors import HttpError from google_auth_oauthlib.flow import InstalledAppFlow from google.auth.transport.requests import Request -from googledrive.models import GoogleApiClientHttpError -from googledrive.models import GoogleApiClientHttpErrorBuilder -from googledrive.mappers import GoogleFileDictToGoogleFile -from googledrive.exceptions import MissingGoogleDriveFolderException -from googledrive.exceptions import MissingGoogleDriveFileException -from googledrive.exceptions import GoogleApiClientHttpErrorException - +from googledrive import models +from googledrive import mappers +from googledrive import exceptions class GoogleAuth: def authenticate(self, credentials, scopes): @@ -131,10 +126,10 @@ def create_folder(self, name): .execute() ) except HttpError as e: - http_error = GoogleApiClientHttpErrorBuilder().from_http_error(e) - raise GoogleApiClientHttpErrorException(http_error) + http_error = models.GoogleApiClientHttpErrorBuilder().from_http_error(e) + raise exceptions.GoogleApiClientHttpErrorException(http_error) - return GoogleFileDictToGoogleFile().google_file_dict_to_google_file(folder) + return mappers.GoogleFileDictToGoogleFile().google_file_dict_to_google_file(folder) def create_file(self, name, mimetype): splitted_path = list(self.__split_path(name)) @@ -145,7 +140,7 @@ def create_file(self, name, mimetype): parent_name = splitted_path[-2] parent_folder = self.get_folder(parent_name) if parent_folder == None: - raise MissingGoogleDriveFolderException( + raise exceptions.MissingGoogleDriveFolderException( "Missing folder: {}".format(parent_name) ) parents = [parent_folder.id] @@ -161,10 +156,10 @@ def create_file(self, name, mimetype): .execute() ) except HttpError as e: - http_error = GoogleApiClientHttpErrorBuilder().from_http_error(e) - raise GoogleApiClientHttpErrorException(http_error) + http_error = models.GoogleApiClientHttpErrorBuilder().from_http_error(e) + raise exceptions.GoogleApiClientHttpErrorException(http_error) - return GoogleFileDictToGoogleFile().google_file_dict_to_google_file(file) + return mappers.GoogleFileDictToGoogleFile().google_file_dict_to_google_file(file) def update_file_parent(self, file_id, current_parent, new_parent): drive_service = super().get_service( @@ -176,8 +171,8 @@ def update_file_parent(self, file_id, current_parent, new_parent): ) file_update.execute() except HttpError as e: - http_error = GoogleApiClientHttpErrorBuilder().from_http_error(e) - raise GoogleApiClientHttpErrorException(http_error) + http_error = models.GoogleApiClientHttpErrorBuilder().from_http_error(e) + raise exceptions.GoogleApiClientHttpErrorException(http_error) def get_file_from_id(self, file_id: str): drive_service = super().get_service( @@ -190,12 +185,12 @@ def get_file_from_id(self, file_id: str): .execute() ) - return GoogleFileDictToGoogleFile().google_file_dict_to_google_file( + return mappers.GoogleFileDictToGoogleFile().google_file_dict_to_google_file( google_file_dict ) except HttpError as e: - http_error = GoogleApiClientHttpErrorBuilder().from_http_error(e) - raise GoogleApiClientHttpErrorException(http_error) + http_error = models.GoogleApiClientHttpErrorBuilder().from_http_error(e) + raise exceptions.GoogleApiClientHttpErrorException(http_error) def list_files(self, page_token: str, query: str): drive_service = super().get_service( @@ -215,11 +210,11 @@ def list_files(self, page_token: str, query: str): .execute() ) except HttpError as e: - http_error = GoogleApiClientHttpErrorBuilder().from_http_error(e) - raise GoogleApiClientHttpErrorException(http_error) + http_error = models.GoogleApiClientHttpErrorBuilder().from_http_error(e) + raise exceptions.GoogleApiClientHttpErrorException(http_error) google_files = [ - GoogleFileDictToGoogleFile().google_file_dict_to_google_file( + mappers.GoogleFileDictToGoogleFile().google_file_dict_to_google_file( google_file_dict ) for google_file_dict in response.get("files", []) @@ -243,8 +238,8 @@ def copy_file(self, file_id, new_filename): ) return results.get("id") except HttpError as e: - http_error = GoogleApiClientHttpErrorBuilder().from_http_error(e) - raise GoogleApiClientHttpErrorException(http_error) + http_error = models.GoogleApiClientHttpErrorBuilder().from_http_error(e) + raise exceptions.GoogleApiClientHttpErrorException(http_error) def create_permission(self, document_id: str, role: str, email_address): drive_service = super().get_service( @@ -256,8 +251,8 @@ def create_permission(self, document_id: str, role: str, email_address): body={"type": "user", "emailAddress": email_address, "role": role}, ).execute() except HttpError as e: - http_error = GoogleApiClientHttpErrorBuilder().from_http_error(e) - raise GoogleApiClientHttpErrorException(http_error) + http_error = models.GoogleApiClientHttpErrorBuilder().from_http_error(e) + raise exceptions.GoogleApiClientHttpErrorException(http_error) # # High level API access @@ -282,7 +277,7 @@ def googledrive_ls(self, path: str): else: folder = self.get_folder(splitted_path[0]) if folder is None: - raise MissingGoogleDriveFolderException( + raise exceptions.MissingGoogleDriveFolderException( "Missing folder: {}".format(splitted_path[0]) ) @@ -291,7 +286,7 @@ def googledrive_ls(self, path: str): folder = self.__get_file(query, path_element) if folder is None: - raise MissingGoogleDriveFolderException( + raise exceptions.MissingGoogleDriveFolderException( "Missing folder: {}".format(path_element) ) @@ -315,7 +310,7 @@ def googledrive_get_file(self, path: str): folder = self.get_folder(splitted_path[0]) if folder is None: - raise MissingGoogleDriveFolderException( + raise exceptions.MissingGoogleDriveFolderException( "Missing folder: {}".format(path[0]) ) @@ -327,7 +322,7 @@ def googledrive_get_file(self, path: str): folder = self.__get_file(query, path_element) if folder is None: - raise MissingGoogleDriveFolderException( + raise exceptions.MissingGoogleDriveFolderException( "Missing folder: {}".format(path_element) ) @@ -365,8 +360,8 @@ def __get_files(self, query: str): page_token = next_page_token return None except HttpError as e: - http_error = GoogleApiClientHttpErrorBuilder().from_http_error(e) - raise GoogleApiClientHttpErrorException(http_error) + http_error = models.GoogleApiClientHttpErrorBuilder().from_http_error(e) + raise exceptions.GoogleApiClientHttpErrorException(http_error) class SheetsService(GoogleService): @@ -396,7 +391,7 @@ def create_spreadsheet(self, filename): # def get_file_values(self, spreadsheet_id, rows_range): if spreadsheet_id is None: - raise MissingGoogleDriveFileException( + raise exceptions.MissingGoogleDriveFileException( "Missing file: {}".format(spreadsheet_id) ) @@ -422,8 +417,8 @@ def get_file_values(self, spreadsheet_id, rows_range): self.cached_file_values.update({spreadsheet_id: {rows_range: values}}) return values except HttpError as e: - http_error = GoogleApiClientHttpErrorBuilder().from_http_error(e) - raise GoogleApiClientHttpErrorException(http_error) + http_error = models.GoogleApiClientHttpErrorBuilder().from_http_error(e) + raise exceptions.GoogleApiClientHttpErrorException(http_error) def update_file_values( self, spreadsheet_id, rows_range, value_input_option, values @@ -506,7 +501,7 @@ def get_file_rows_from_folder( google_file = super().googledrive_get_file(file_path) if google_file is None: - raise MissingGoogleDriveFileException("Missing file: {}".format(filename)) + raise exceptions.MissingGoogleDriveFileException("Missing file: {}".format(filename)) values = super().get_file_values(google_file.id, rows_range) diff --git a/googledrive/cli.py b/googledrive/cli.py index 9a98582..3518a01 100644 --- a/googledrive/cli.py +++ b/googledrive/cli.py @@ -1,9 +1,7 @@ -import sys import click -from googledrive.api import GoogleAuth -from googledrive.api import GoogleDrive -from googledrive.exceptions import GoogleApiClientHttpErrorException +from googledrive import api +from googledrive import exceptions class Config: @@ -24,7 +22,7 @@ class Config: @click.argument("credentials", envvar="CREDENTIALS", type=click.Path(exists=True)) def login(credentials): """Perform a login with google oauth""" - GoogleAuth().authenticate(credentials=credentials, scopes=Config.SCOPES) + api.GoogleAuth().authenticate(credentials=credentials, scopes=Config.SCOPES) @click.command() @@ -33,9 +31,9 @@ def login(credentials): def ls(credentials, path): """List directory contents""" try: - google_drive = GoogleDrive(credentials, Config.SCOPES) + google_drive = api.GoogleDrive(credentials, Config.SCOPES) files = google_drive.googledrive_ls(path) - except GoogleApiClientHttpErrorException as e: + except exceptions.GoogleApiClientHttpErrorException as e: error = e.get_google_api_client_http_error() print(f"An http exception occured requesting google's API:\n") print(f" - Code: {error.code}") @@ -55,9 +53,9 @@ def ls(credentials, path): def get(id, credentials): """Get file metadata""" try: - google_drive = GoogleDrive(credentials, Config.SCOPES) + google_drive = api.GoogleDrive(credentials, Config.SCOPES) google_file = google_drive.get_file_from_id(id) - except GoogleApiClientHttpErrorException as e: + except exceptions.GoogleApiClientHttpErrorException as e: error = e.get_google_api_client_http_error() print(f"An http exception occured requesting google's API:\n") print(f" - Code: {error.code}") @@ -84,9 +82,9 @@ def get(id, credentials): def mkdir(credentials, name): """Make directory""" try: - google_drive = GoogleDrive(credentials, Config.SCOPES) + google_drive = api.GoogleDrive(credentials, Config.SCOPES) folder = google_drive.create_folder(name) - except GoogleApiClientHttpErrorException as e: + except exceptions.GoogleApiClientHttpErrorException as e: error = e.get_google_api_client_http_error() print(f"An http exception occured requesting google's API:\n") print(f" - Code: {error.code}") @@ -104,9 +102,9 @@ def mkdir(credentials, name): def get_mimetypes(credentials): """Get Mimetypes availables in this API implementation""" try: - google_drive = GoogleDrive(credentials, Config.SCOPES) + google_drive = api.GoogleDrive(credentials, Config.SCOPES) mimetypes = google_drive.get_mymetypes() - except GoogleApiClientHttpErrorException as e: + except exceptions.GoogleApiClientHttpErrorException as e: error = e.get_google_api_client_http_error() print(f"An http exception occured requesting google's API:\n") print(f" - Code: {error.code}") @@ -127,9 +125,9 @@ def get_mimetypes(credentials): def touch(credentials, mymetype, name): """Create empty file of specified mimetype""" try: - google_drive = GoogleDrive(credentials, Config.SCOPES) + google_drive = api.GoogleDrive(credentials, Config.SCOPES) file = google_drive.create_file(name=name, mimetype=mymetype) - except GoogleApiClientHttpErrorException as e: + except exceptions.GoogleApiClientHttpErrorException as e: error = e.get_google_api_client_http_error() print(f"An http exception occured requesting google's API:\n") print(f" - Code: {error.code}") diff --git a/googledrive/exceptions.py b/googledrive/exceptions.py index 054b196..5b0c021 100644 --- a/googledrive/exceptions.py +++ b/googledrive/exceptions.py @@ -1,4 +1,4 @@ -from googledrive.models import GoogleApiClientHttpError +from googledrive import models class CustomException(Exception): @@ -16,7 +16,7 @@ def get_str(self, class_name): class GoogleApiClientHttpErrorException(Exception): - def __init__(self, google_api_client_http_error: GoogleApiClientHttpError): + def __init__(self, google_api_client_http_error: models.GoogleApiClientHttpError): self.google_api_client_http_error = google_api_client_http_error def get_google_api_client_http_error(self): diff --git a/googledrive/mappers.py b/googledrive/mappers.py index c4c34e6..22c7669 100644 --- a/googledrive/mappers.py +++ b/googledrive/mappers.py @@ -1,4 +1,4 @@ -from googledrive.models import GoogleFile +from googledrive import models class GoogleFileDictToGoogleFile: @@ -12,7 +12,7 @@ def google_file_dict_to_google_file(self, google_file_dict): mime_type = google_file_dict.get("mimeType") or "" export_links = google_file_dict.get("exportLinks") or {} - return GoogleFile( + return models.GoogleFile( name=name, id=id, parents=parents, diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..29d182a --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,63 @@ +[build-system] +requires = ["setuptools >= 77.0.3"] +build-backend = "setuptools.build_meta" + +[project] +name = "google-drive" +description = "Library and cli to manage and interact with your Google Drive" +readme = {file = "README.md", content-type = "text/markdown"} +version = "0.5.1" +requires-python = '>=3.9.21' +dependencies = [ + "google-api-core==1.31.5", + "google-api-python-client==2.166.0", + "google-auth==1.35.0", + "google-auth-httplib2==0.2.0", + "google-auth-oauthlib==0.4.1", + "googleapis-common-protos==1.56.0", + "dataclasses==0.6", + "click==8.1.7" +] +authors = [ + {name = "Eduardo Garcia", email = "garciaruiz.edu+maintain+google-drive-python@gmail.com"}, +] +maintainers = [ + {name = "Eduardo Garcia", email = "garciaruiz.edu+maintain+google-drive-python@gmail.com"}, +] +license = "Apache-2.0" +license-files = [ + "LICENSE*", + "setuptools/_vendor/LICENSE*", +] +keywords = ["google", "drive", "cli"] + +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Topic :: Software Development :: Libraries", +] + +[project.optional-dependencies] +dev = [ + "pylint==2.16.0b1", + "autopep8==2.0.1", + "pytest==8.3.5", + "pytest-cov==6.1.1", + "ipython==7.23.1", + "twine==6.1.0" +] + +[project.scripts] +google-drive = "googledrive.cli:googledrive" + +[project.entry-points."console_scripts"] +google-drive = "googledrive.cli:googledrive" + +[project.urls] +Homepage = "https://github.com/eduardogr/google-drive-python" +Documentation = "https://github.com/eduardogr/google-drive-python" +Repository = "https://github.com/eduardogr/google-drive-python.git" +Issues = "https://github.com/eduardogr/google-drive-python/issues" +Changelog = "https://github.com/eduardogr/google-drive-python/blob/main/CHANGELOG.md" + +[tool.setuptools.packages.find] +where = ["googledrive"] \ No newline at end of file diff --git a/requirements/dev.txt b/requirements/dev.txt deleted file mode 100644 index 9ecf8ba..0000000 --- a/requirements/dev.txt +++ /dev/null @@ -1,16 +0,0 @@ -# linter -pylint==2.16.0b1 - -# format python code to PEP 8 stlye guide -autopep8==2.0.1 - -# test runner -pytest==7.2.1 -pytest-cov==4.0.0 - -# upgraded Python shell for dev env -ipython==7.23.1 - -codecov==2.1.12 - -twine==4.0.2 \ No newline at end of file diff --git a/requirements/prod.txt b/requirements/prod.txt deleted file mode 100644 index 1a191c9..0000000 --- a/requirements/prod.txt +++ /dev/null @@ -1,10 +0,0 @@ -google-api-core==1.31.5 -google-api-python-client==2.6.0 -google-auth==1.35.0 -google-auth-httplib2==0.1.0 -google-auth-oauthlib==0.4.1 -googleapis-common-protos==1.56.0 - -dataclasses==0.6 - -click==8.1.7 \ No newline at end of file diff --git a/setup.py b/setup.py deleted file mode 100644 index cd09559..0000000 --- a/setup.py +++ /dev/null @@ -1,48 +0,0 @@ -import os -import pathlib - -import pkg_resources -from setuptools import setup - - -def read(fname): - this_directory = pathlib.Path(__file__).parent - long_description = (this_directory / fname).read_text() - return long_description - - -def read_requirements(path): - with pathlib.Path(path).open() as requirements_txt: - return [ - str(requirement) - for requirement in pkg_resources.parse_requirements(requirements_txt) - ] - - -requirements = read_requirements("requirements/prod.txt") -extra_requirements_dev = read_requirements("requirements/dev.txt") - - -setup( - name="google-drive", - version="0.5.1", - author="Eduardo Garcia", - author_email="garciaruiz.edu+maintain+google-drive-python@gmail.com", - maintainer="Eduardo GarcĂ­a", - maintainer_email="garciaruiz.edu+google-drive-python@gmail.com", - description=("Library and cli to manage and interact with your Google Drive"), - license="Apache", - keywords="google drive", - url="https://github.com/eduardogr/google-drive-python", - packages=["googledrive"], - install_requires=requirements, - extras_require={"dev": extra_requirements_dev}, - long_description=read("README.md"), - long_description_content_type="text/markdown", - classifiers=[ - "Development Status :: 5 - Production/Stable", - "Topic :: Software Development :: Libraries", - "License :: OSI Approved :: Apache Software License", - ], - entry_points={"console_scripts": ["google-drive = googledrive.cli:googledrive"]}, -) diff --git a/tests/test_api.py b/tests/test_api.py index 9cef113..e0dfb69 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -1,11 +1,8 @@ from unittest import TestCase -from googledrive.api import FilesAPI, GoogleDrive -from googledrive.api import SheetsService, DocsService -from googledrive.models import GoogleFile -from googledrive.exceptions import MissingGoogleDriveFolderException -from googledrive.exceptions import MissingGoogleDriveFileException -from googledrive.exceptions import GoogleApiClientHttpErrorException +from googledrive import api +from googledrive import models +from googledrive import exceptions from tests.common.mocks import RawSheetsServiceMock from tests.common.mocks import RawDocsServiceMock @@ -17,28 +14,28 @@ from tests.common.mocks import MockDocsService -class DocServiceSut(DocsService, MockGoogleService): +class DocServiceSut(api.DocsService, MockGoogleService): "Inject a mock into the DocsService dependency" def __init__(self): super().__init__("", []) -class SheetsServiceSut(SheetsService, MockGoogleService): +class SheetsServiceSut(api.SheetsService, MockGoogleService): "Inject a mock into the SheetsService dependency" def __init__(self): super().__init__("", []) -class GoogleDriveSut(GoogleDrive, MockGoogleService): +class GoogleDriveSut(api.GoogleDrive, MockGoogleService): "Inject a mock into the GoogleDrive dependency" def __init__(self): super().__init__("", []) -class FilesAPISut(FilesAPI, MockGoogleDrive, MockSheetsService, MockDocsService): +class FilesAPISut(api.FilesAPI, MockGoogleDrive, MockSheetsService, MockDocsService): "Inject mocks into FilesAPI dependencies" @@ -51,8 +48,8 @@ def setUp(self): drive_service = RawGoogleServiceMock(raw_google_service_files) self.sut.set_service( - GoogleDrive.DRIVE_SERVICE_ID, - GoogleDrive.DRIVE_SERVICE_VERSION, + api.GoogleDrive.DRIVE_SERVICE_ID, + api.GoogleDrive.DRIVE_SERVICE_VERSION, drive_service, ) @@ -63,7 +60,7 @@ def test_create_folder_ok(self): def test_create_file_when_no_parent_ok(self): path = "filename" - mimetype = GoogleDrive.MIMETYPE_DOCUMENT + mimetype = api.GoogleDrive.MIMETYPE_DOCUMENT self.sut.create_file(path, mimetype) @@ -71,14 +68,14 @@ def test_create_file_when_parent_ok(self): # given: parent_folder = "parentfolder" path = f"{parent_folder}/filename" - mimetype = GoogleDrive.MIMETYPE_DOCUMENT + mimetype = api.GoogleDrive.MIMETYPE_DOCUMENT files = [{"name": parent_folder, "id": parent_folder, "parents": []}] - files_by_query = {GoogleDrive.QUERY_IS_FOLDER: RawGoogleListMock(files)} + files_by_query = {api.GoogleDrive.QUERY_IS_FOLDER: RawGoogleListMock(files)} raw_google_service_files = RawGoogleServiceFilesMock(files_by_query) drive_service = RawGoogleServiceMock(raw_google_service_files) self.sut.set_service( - GoogleDrive.DRIVE_SERVICE_ID, - GoogleDrive.DRIVE_SERVICE_VERSION, + api.GoogleDrive.DRIVE_SERVICE_ID, + api.GoogleDrive.DRIVE_SERVICE_VERSION, drive_service, ) @@ -87,7 +84,7 @@ def test_create_file_when_parent_ok(self): def test_googledrive_ls_when_folder_no_exists(self): # when: - with self.assertRaises(MissingGoogleDriveFolderException): + with self.assertRaises(exceptions.MissingGoogleDriveFolderException): self.sut.googledrive_ls("/unexistent") def test_googledrive_ls_when_for(self): @@ -99,7 +96,7 @@ def test_googledrive_ls_when_for(self): ] files_by_query = { "mimeType='application/vnd.google-apps.folder'": RawGoogleListMock(files), - f"{GoogleDrive.QUERY_IS_FILE} and 'basefolder' in parents": RawGoogleListMock( + f"{api.GoogleDrive.QUERY_IS_FILE} and 'basefolder' in parents": RawGoogleListMock( listed_files ), } @@ -107,8 +104,8 @@ def test_googledrive_ls_when_for(self): drive_service = RawGoogleServiceMock(raw_google_service_files) self.sut.set_service( - GoogleDrive.DRIVE_SERVICE_ID, - GoogleDrive.DRIVE_SERVICE_VERSION, + api.GoogleDrive.DRIVE_SERVICE_ID, + api.GoogleDrive.DRIVE_SERVICE_VERSION, drive_service, ) @@ -130,13 +127,13 @@ def test_googledrive_ls_when_for_none(self): drive_service = RawGoogleServiceMock(raw_google_service_files) self.sut.set_service( - GoogleDrive.DRIVE_SERVICE_ID, - GoogleDrive.DRIVE_SERVICE_VERSION, + api.GoogleDrive.DRIVE_SERVICE_ID, + api.GoogleDrive.DRIVE_SERVICE_VERSION, drive_service, ) # when: - with self.assertRaises(MissingGoogleDriveFolderException): + with self.assertRaises(exceptions.MissingGoogleDriveFolderException): self.sut.googledrive_ls("/something/unexistent") def test_googledrive_ls_when_no_for(self): @@ -145,13 +142,13 @@ def test_googledrive_ls_when_no_for(self): {"name": "file_1", "id": "file_1", "parents": []}, {"name": "file_2", "id": "file_2", "parents": []}, ] - files_by_query = {GoogleDrive.QUERY_IS_FILE: RawGoogleListMock(listed_files)} + files_by_query = {api.GoogleDrive.QUERY_IS_FILE: RawGoogleListMock(listed_files)} raw_google_service_files = RawGoogleServiceFilesMock(files_by_query) drive_service = RawGoogleServiceMock(raw_google_service_files) self.sut.set_service( - GoogleDrive.DRIVE_SERVICE_ID, - GoogleDrive.DRIVE_SERVICE_VERSION, + api.GoogleDrive.DRIVE_SERVICE_ID, + api.GoogleDrive.DRIVE_SERVICE_VERSION, drive_service, ) @@ -170,7 +167,7 @@ def test_googledrive_get_file_when_incorrect_path(self): def test_googledrive_get_file_when_unexistent_file(self): # when: - with self.assertRaises(MissingGoogleDriveFolderException): + with self.assertRaises(exceptions.MissingGoogleDriveFolderException): self.sut.googledrive_get_file("/unexistent/path/file") def test_googledrive_get_file_for(self): @@ -184,11 +181,11 @@ def test_googledrive_get_file_for(self): {"name": "existent_file", "id": "existent_file", "parents": ["path"]}, ] files_by_query = { - GoogleDrive.QUERY_IS_FOLDER: RawGoogleListMock(files), - f"{GoogleDrive.QUERY_IS_FOLDER} and 'base' in parents": RawGoogleListMock( + api.GoogleDrive.QUERY_IS_FOLDER: RawGoogleListMock(files), + f"{api.GoogleDrive.QUERY_IS_FOLDER} and 'base' in parents": RawGoogleListMock( files ), - f"{GoogleDrive.QUERY_IS_FILE} and 'path' in parents": RawGoogleListMock( + f"{api.GoogleDrive.QUERY_IS_FILE} and 'path' in parents": RawGoogleListMock( listed_files ), } @@ -196,8 +193,8 @@ def test_googledrive_get_file_for(self): drive_service = RawGoogleServiceMock(raw_google_service_files) self.sut.set_service( - GoogleDrive.DRIVE_SERVICE_ID, - GoogleDrive.DRIVE_SERVICE_VERSION, + api.GoogleDrive.DRIVE_SERVICE_ID, + api.GoogleDrive.DRIVE_SERVICE_VERSION, drive_service, ) @@ -210,20 +207,20 @@ def test_googledrive_get_file_for_none(self): # given: files = [{"name": "base", "id": "base", "parents": []}] files_by_query = { - GoogleDrive.QUERY_IS_FOLDER: RawGoogleListMock(files), - f"{GoogleDrive.QUERY_IS_FOLDER} and 'base' in parents": RawGoogleListMock(), + api.GoogleDrive.QUERY_IS_FOLDER: RawGoogleListMock(files), + f"{api.GoogleDrive.QUERY_IS_FOLDER} and 'base' in parents": RawGoogleListMock(), } raw_google_service_files = RawGoogleServiceFilesMock(files_by_query) drive_service = RawGoogleServiceMock(raw_google_service_files) self.sut.set_service( - GoogleDrive.DRIVE_SERVICE_ID, - GoogleDrive.DRIVE_SERVICE_VERSION, + api.GoogleDrive.DRIVE_SERVICE_ID, + api.GoogleDrive.DRIVE_SERVICE_VERSION, drive_service, ) # when: - with self.assertRaises(MissingGoogleDriveFolderException): + with self.assertRaises(exceptions.MissingGoogleDriveFolderException): self.sut.googledrive_get_file("/base/unexistent/unexistent_file") def test_googledrive_get_file_no_for(self): @@ -234,8 +231,8 @@ def test_googledrive_get_file_no_for(self): {"name": "existent_file", "id": "existent_file", "parents": ["path"]}, ] files_by_query = { - GoogleDrive.QUERY_IS_FOLDER: RawGoogleListMock(files), - f"{GoogleDrive.QUERY_IS_FILE} and 'base' in parents": RawGoogleListMock( + api.GoogleDrive.QUERY_IS_FOLDER: RawGoogleListMock(files), + f"{api.GoogleDrive.QUERY_IS_FILE} and 'base' in parents": RawGoogleListMock( listed_files ), } @@ -243,8 +240,8 @@ def test_googledrive_get_file_no_for(self): drive_service = RawGoogleServiceMock(raw_google_service_files) self.sut.set_service( - GoogleDrive.DRIVE_SERVICE_ID, - GoogleDrive.DRIVE_SERVICE_VERSION, + api.GoogleDrive.DRIVE_SERVICE_ID, + api.GoogleDrive.DRIVE_SERVICE_VERSION, drive_service, ) @@ -284,8 +281,8 @@ class TestSheetsService(TestCase): def setUp(self): self.sut = SheetsServiceSut() self.sut.set_service( - SheetsService.SHEETS_SERVICE_ID, - SheetsService.SHEETS_SERVICE_VERSION, + api.SheetsService.SHEETS_SERVICE_ID, + api.SheetsService.SHEETS_SERVICE_VERSION, RawSheetsServiceMock(), ) @@ -319,8 +316,8 @@ class TestDocsService(TestCase): def setUp(self): self.sut = DocServiceSut() self.sut.set_service( - DocsService.DOCS_SERVICE_ID, - DocsService.DOCS_SERVICE_VERSION, + api.DocsService.DOCS_SERVICE_ID, + api.DocsService.DOCS_SERVICE_VERSION, RawDocsServiceMock(), ) @@ -365,7 +362,7 @@ def test_create_spreadsheet(self): # given: folder_parent = "parent" filename = "filename" - folder = GoogleFile( + folder = models.GoogleFile( id="new_parent_id", name="folder", parents=[], mime_type="", export_links={} ) @@ -411,7 +408,7 @@ def test_correct_number_executions_when_get_folder_and_exists(self): self.sut.set_pages_requested(1) self.sut.set_response_files( [ - GoogleFile( + models.GoogleFile( id="some id", name=folder_name, parents=[], @@ -443,7 +440,7 @@ def test_correct_query_when_get_folder(self): self.assertEqual(1, len(calls)) self.assertIn("list_files", calls) - self.assertEqual(GoogleDrive.QUERY_IS_FOLDER, calls["list_files"][0]["query"]) + self.assertEqual(api.GoogleDrive.QUERY_IS_FOLDER, calls["list_files"][0]["query"]) def test_get_file_rows_from_folder(self): # given: @@ -452,7 +449,7 @@ def test_get_file_rows_from_folder(self): file_id = "file_id" self.sut.set_googledrive_get_file_response( f"/{foldername}/{filename}", - GoogleFile( + models.GoogleFile( id=file_id, name=filename, parents=[], mime_type="", export_links={} ), ) @@ -481,7 +478,7 @@ def test_get_file_rows_from_folder_when_missing_google_folder_exception(self): self.sut.set_googledrive_get_file_raise_exception(f"/{foldername}/{filename}") # when: - with self.assertRaises(MissingGoogleDriveFolderException): + with self.assertRaises(exceptions.MissingGoogleDriveFolderException): self.sut.get_file_rows_from_folder(foldername, filename, rows_range) # then: @@ -498,7 +495,7 @@ def test_get_file_rows_from_folder_when_missing_google_file_exception(self): rows_range = "A2::F4" # when: - with self.assertRaises(MissingGoogleDriveFileException): + with self.assertRaises(exceptions.MissingGoogleDriveFileException): self.sut.get_file_rows_from_folder(foldername, filename, rows_range) # then: @@ -528,7 +525,7 @@ def test_get_file_rows_when_http_error(self): self.sut.raise_exception_for_get_file_values_for_ids([file_id]) # when: - with self.assertRaises(GoogleApiClientHttpErrorException): + with self.assertRaises(exceptions.GoogleApiClientHttpErrorException): self.sut.get_file_values(file_id, rows_range) # then: diff --git a/tests/test_mappers.py b/tests/test_mappers.py index 3ec8f61..db2b288 100644 --- a/tests/test_mappers.py +++ b/tests/test_mappers.py @@ -1,17 +1,17 @@ from unittest import TestCase -from googledrive.mappers import GoogleFileDictToGoogleFile -from googledrive.models import GoogleFile +from googledrive import mappers +from googledrive import models class TestGoogleFileDictToGoogleFile(TestCase): def test_to_json(self): # given: google_file_dict = {"name": "id", "id": "name", "parents": "[]"} - expected_google_file = GoogleFile( + expected_google_file = models.GoogleFile( id="id", name="name", parents=[], mime_type="", export_links={} ) - sut = GoogleFileDictToGoogleFile() + sut = mappers.GoogleFileDictToGoogleFile() # when: json_dict = sut.google_file_dict_to_google_file(google_file_dict) @@ -23,7 +23,7 @@ def test_to_json_when_is_none(self): # given: google_file_dict = None expected_google_file = None - sut = GoogleFileDictToGoogleFile() + sut = mappers.GoogleFileDictToGoogleFile() # when: json_dict = sut.google_file_dict_to_google_file(google_file_dict)