[PYTHON] Duplicate the document template prepared in Google Drive with PyDrive2

Introduction

In this article, I will take up PyDrive2 (GitHub) from among the packages that operate Google Drive with Python. As a memorandum, I will summarize how to operate Google Drive from PyDrive2 via Drive API and duplicate the specified document.

About PyDrive2

PyDrive2 is a maintained fork of PyDrive. Updates to PyDrive have been stopped for over a year, and PyDrive 2 was released in January 2020.

Please check the following for a little more detailed explanation and settings around authentication when using PyDrive2. Authentication of package PyDrive2 that operates Google Drive with Python

Note that PyDrive and PyDrive2 access the Drive API ** v2 **. Please note that the Drive API also has v3.

Operating environment

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.14.6
BuildVersion:   18G3020
$ python -V
Python 3.8.1
$ pip list | grep PyDrive2
PyDrive2                 1.4.10

The files are placed according to Authentication of package PyDrive2 that operates Google Drive with Python.

.
├── my_client_secrets.json
├── saved_credentials.json
└── settings.yaml

Thing you want to do

Let the Python script do a ** copy of the minutes template ** of Google Docs.

background

We jointly take minutes with Google Docs during MTG.

テンプレートドキュメント例.png

I found it boring to duplicate the minutes template for each MTG and started thinking about automation. So, as a first step in automation, I created a script that ** duplicates when you specify the ID of Google Docs **.

What is Google Docs ID?

The URL of Google Docs is as follows.

https://docs.google.com/document/d/1******************************************o/edit#

Of these, 1 ********************************************* o The part is the ID (the asterisk is used to mean masking).

Python script that duplicates the specified document

copy_template.py


import argparse

from pydrive2.auth import GoogleAuth
from pydrive2.drive import GoogleDrive


def main():
    #Parsing the arguments passed from the command line(1)
    parser = argparse.ArgumentParser()
    parser.add_argument("source_id")
    args = parser.parse_args()
    source_id = args.source_id

    #Get objects to work with Google Drive(2)
    gauth = GoogleAuth()
    gauth.LocalWebserverAuth()
    drive = GoogleDrive(gauth)

    #Copied to the name of the source file_File name with(3)
    source = drive.CreateFile({"id": source_id})
    source.FetchMetadata("title")
    dest_title = f"copied_{source['title']}"

    #Make a copy(4)
    copied_file = {"title": dest_title}
    f = (
        drive.auth.service.files()
        .copy(fileId=source_id, body=copied_file)
        .execute()
    )

    #Display the URL to access the created file(5)
    dest = drive.CreateFile({"id": f["id"]})
    dest.FetchMetadata("alternateLink")
    print(dest["alternateLink"])


if __name__ == "__main__":
    main()

Execution result

File placement


.
├── copy_template.py
├── my_client_secrets.json
├── saved_credentials.json
└── settings.yaml

How to use


$ python copy_template.py --help
usage: copy_template.py [-h] source_id

positional arguments:
  source_id

optional arguments:
  -h, --help  show this help message and exit

When executed, the URL of the duplicated document will be displayed.

$ python copy_template.py 1******************************************o
https://docs.google.com/document/d/1******************************************c/edit?usp=drivesdk

Code commentary

I couldn't find a way to duplicate (copy) the specified document in PyDrive Documents [^ 1] .. So I searched PyDrive's Issue and found an Issue that I could refer to. Create a copy of the file #85 (Comment) It is implemented according to this.

[^ 1]: The PyDrive document is shown as the PyDrive2 document (as of May 2020).

Replication mechanism (code (4))

Based on the authentication result, create an object (gdrive) to operate Google Drive.

Duplicate requires the ID of the source document and the title of the destination document.

--Document ID of copy source: Passed from the command line --Reproduction destination title: It's OK even if it's fixed. This time, add the prefix copied_ to the title of the source document.

Get Google Drive files (code (3))

To work with files on Google Drive from the gdrive object, use the CreateFile method.

source = drive.CreateFile({"id": source_id})

The return value of the CreateFile method is a GoogleDriveFile instance. ** Specify an ID ** and Create File to make the file workable via the GoogleDriveFile instance.

Get metadata for Google Drive files (codes (3), (5))

There is various information (meta data) in the file of Google Drive, but only the ID can be obtained by the above method. If you have the information you want to get

  1. Specify the attribute you want to get with the FetchMetadata method of GoogleDriveFile --Example: source.FetchMetadata ("title ")
  2. Access using the attribute name you want to acquire as a key --Example: source ['title']

It becomes the procedure.

If you want to specify the attribute you want to get in 1, specify it according to the following reference. https://developers.google.com/drive/api/v2/reference/files

Copy files from Google Drive (code (4))

Since GoogleDrive and GoogleDriveFile do not have a method to make a copy of a file, it seems that the Files: copy endpoint is called directly from the google-api-python-client that PyDrive2 wraps. is.

Doesn't it work on a shared drive?

If you want to specify the ID of the document on the shared drive, you need to change the code (4) to copy. Pass True in the supportsAllDrives argument.

copy_template.py


    #Make a copy(4)
    copied_file = {"title": dest_title}
    f = (
        drive.auth.service.files()
        .copy(fileId=source_id, body=copied_file, supportsAllDrives=True)
        .execute()
    )

According to https://developers.google.com/drive/api/v2/enable-shareddrives

supportsAllDrives — Whether the requesting application supports both My Drives and shared drives. If false, then shared drive items are not included in the response.

Therefore, you can also operate files on the shared drive by specifying True. If you don't specify this argument, the Drive API will return File not found.

Files in My Drive can be copied even if supportsAllDrives = True is specified. Therefore, you can always specify it, but it seems that you do not need to specify it after June 2020. According to Files: copy endpoint documentation, after June 1, 2020, the supportsAllDrives argument will be It is obsolete and you can work with files on the shared drive without specifying it [^ 4].

As for the operation of the shared drive, some issues were seen in PyDrive [^ 2], but it seems that it is supported in PyDrive2 [^ 3].

[^ 3]: It was captured in Commit in January 2020

Can the scope be narrowed down?

As mentioned in Authentication of package PyDrive2 that operates Google Drive with Python, a wide scope (https://www.googleapis.com / auth / drive) is used. I tried to specify whether this can be narrowed down when duplicating the file, but I could not narrow it down [^ 5].

[^ 5]: I tried drive.file, drive.metadata and their combinations as scopes, but [The user has not granted the app {appId} {verb} access to the file {fileId}]( The error https://developers.google.com/drive/api/v2/handle-errors#resolve_a_403_error_the_user_has_not_granted_the_app_appid_verb_access_to_the_file_fileid) has not been resolved.

I referred to Files: copy endpoint scope and found that https://www.googleapis. From com / auth / drive, I found that it was not possible to narrow down.

At the end

I summarized how to duplicate by specifying the ID of Google Docs in PyDrive2.

Both documents and spreadsheets are files when viewed from Google Drive. Therefore, I think that it is possible to duplicate other than the document by this method (to be verified at a later date).

Recommended Posts

Duplicate the document template prepared in Google Drive with PyDrive2
Around the authentication of PyDrive2, a package that operates Google Drive with Python
Implement Sign In With Google on the backend side
How to load files in Google Drive with Google Colaboratory
Mount google drive with google-drive-ocamlfuse
Access Google Drive with Python
Regularly upload files to Google Drive using the Google Drive API in Python
Download Google Drive files in Python
Create and edit spreadsheets in any folder on Google Drive with python
Implemented in Dataflow to copy the hierarchy from Google Drive to Google Cloud Storage
Load csv with duplicate columns in pandas
Behavior when returning in the with block
Display Python 3 in the browser with MAMP
How to search Google Drive with Google Colaboratory
Get holidays with the Google Calendar API
Upload images to Google Drive with Python