Upload updated a file on Google Drive with Python using Drive API V3 does not work - python-3.x

I would not post this here but I invested hours now into understanding why the last part of my Python script does not behave as I expect it to behave reading documentation and many other posts on this topic.
What I want to achieve.
Create project in Google Cloud Platform and enable Drive API - works
Create OAuth credentials for Drive API - works
Authenticate with Google Drive from Python script - works
Download the file I want to edit with Python script - works
Upload the modified file after edit with Python script - does not work
I am using this function from the official Google documentation: https://developers.google.com/drive/api/v2/reference/files/update
But it gives the following error:
raise TypeError('Got an unexpected keyword argument "%s"' % name)
TypeError: Got an unexpected keyword argument "newRevision"
When I remove it from the function call I am getting this:
An error occurred:
<HttpError 403 when requesting https://www.googleapis.com/upload/drive/v3/files/1T1dl_Z3z-FDLa7lbWib8XxgbTd5pMpIP?alt=json&uploadType=resumable returned "The resource body includes fields which are not directly writable.">
I do not understand why I am getting this.
Why does the official sample contain a parameter that is not supported?
Is it possible that I am using a different version of the Google Python libraries locally then they expect me to have? I just followed the official documentation again?
Is is possible that I do not have sufficient rights to update the file?
Thanks,
Andre

Meanwhile I figured it out by myself why it was not working.
If you follow the Python Google Drive Quick Onboarding you will use version 3 of their API: https://developers.google.com/drive/api/v3/quickstart/python
This line defines the version:
service = build('drive', 'v3', credentials=creds)
If you continue searching in their documentation for a functionality to update a file I ended up here in the version 2 documentation and snippets:
https://developers.google.com/drive/api/v2/reference/files/update
Looking here for the version 3 snippet there is none existing in their documentation: https://developers.google.com/drive/api/v3/reference/files/update
So I assumed it is still valid what they posted for version 2, but this is not the case.
I did everything now in version 2 and it is finally working.
Edit to add reference:
newRevision is a valid parameter in v2, but not in v3, so I assume that, in v3, blob uploads always create a new revision (that's what happens in v2 if this parameter is not set – default is true). See Parameter differences between v2 and v3:
+--------------+--------------+--------------+
| Method | v2 Parameter | v3 Parameter |
+--------------+--------------+--------------+
| files.update | newRevision | n/a |
+--------------+--------------+--------------+

Related

What is suggested method to get service versions

What is the best way to get list of service versions in google app engine in flex env? (from service instance in Python 3). I want to authenticate using service account json keys file. I need to find currently default version (with most of traffic).
Is there any lib I can use like googleapiclient.discovery, or google.appengine.api.modules? Or I should build it from scratches and request REST api on apps.services.versions.list using oauth? I couldn't not find any information in google docs..
https://cloud.google.com/appengine/docs/standard/python3/python-differences#cloud_client_libraries
Finally I was able to solve it. Simple things on GAE became big problems..
SOLUTION:
I have path to service_account.json set in GOOGLE_APPLICATION_CREDENTIALS env variable. Then you can use google.auth.default
from googleapiclient.discovery import build
import google.auth
creds, project = google.auth.default(scopes=['https://www.googleapis.com/auth/cloud-platform.read-only'])
service = build('appengine', 'v1', credentials=creds, cache_discovery=False)
data = service.apps().services().get(appsId=APPLICATION_ID, servicesId=SERVICE_ID).execute()
print data['split']['allocations']
Return value is allocations dictionary with versions as keys and traffic percents in values.
All the best!
You can use Google's Python Client Library to interact with the Google App Engine Admin API, in order to get the list of a GAE service versions.
Once you have google-api-python-client installed, you might want to use the list method to list all services in your application:
list(appsId, pageSize=None, pageToken=None, x__xgafv=None)
The arguments of the method should include the following:
appsId: string, Part of `name`. Name of the resource requested. Example: apps/myapp. (required)
pageSize: integer, Maximum results to return per page.
pageToken: string, Continuation token for fetching the next page of results.
x__xgafv: string, V1 error format. Allowed values: v1 error format, v2 error format
You can find more information on this method in the link mentioned above.

Google Cloud Natural Language Example

I have followed the getting started page closely.
https://cloud.google.com/natural-language/docs/reference/libraries#client-libraries-install-php
The example code has the following: $projectId = 'YOUR_PROJECT_ID';
I fill in my project id taken from the json file and the Google console--e.g. "$projectID = 'myproject-197218'" and I always get a fatal error with "Permission Denied."
I have set the env variable, run composer to install the library. And, I created the Google json file. I am running the example in PHP code.
I am running the code on my local server (xampp).
I figured out my problem. The Google Cloud json file was stored on my drive d:, so in the env variable I referenced it as 'GOOGLE_APPLICATION_CREDENTIALS= d:\xampp\htdocs\googapi\mproj.json', it did not work; when I moved it to the root of the c: drive and referenced it there (GOOGLE_APPLICATION_CREDENTIALS=c:proj.json), it worked fine.
Are you sure that the ID of your project is that one? I'm working in Google Cloud and I cannot see this project ID in our database, but if I type "my-project-197218" with a "-" between "my" and "project" I am able to find one project. please, to make sure that this is your correct project ID, run this command in your Google Cloud Shell to get the default project ID:
gcloud config list --format 'value(core.project)' 2>/dev/null

Facebook Graph API version not supported

I want to access a facebook page data, and my fb Graph API version is 3.1, when i am writting this(in python):
graph = facebook.GraphAPI(access_token=token, version = 3.1)
it gives a version error, i.e:
facebook.GraphAPIError: Valid API versions are '2.7', '2.8', '2.9', '2.10', '2.11', '2.12', '3.0'
how can i access facebook Graph API through my version in python.
Thanks in advance.
You will either
have to use an app id that still allows you to use a lower API version, or
wait for an update of the library, or
see where the library does this check and manually add 3.1 to the list there.
If you are using this library https://github.com/mobolic/facebook-sdk/, you can edit the __init__.py file, which currently contains the following line:
VALID_API_VERSIONS = ["2.7", "2.8", "2.9", "2.10", "2.11", "2.12", "3.0"]
If you add "3.1" to that list, you should be able to use API version 3.1 without getting this error.

What is the Azure API version

I'm trying to access the result of a GET request provided by Azure, as shown in the example : https://msdn.microsoft.com/sv-se/library/azure/dn820159.aspx
My problem is that the api-version is a mandatory argument, but I have no idea about what to write inside. I'm a bit lost with the Azure Batch documentation, it doesn't seem to be complete.
I found something in an Azure webpage : https://azure.microsoft.com/en-us/documentation/articles/search-api-versions/ and the api-version was api-version=2015-02-28. However, if I try it in my browser, I have this answer : "key":"Reason","value":"The specified api version string is invalid".
Any idea of what I can put inside the api-version parameter ?
Have a look here
As the time of this writing
The version of the Batch API described here is '2016-07-01.3.1', and
using that version is recommended where possible.
Earlier versions include '2016-02-01.3.0', '2015-12-01.2.1',
'2015-11-01.2.1', '2015-06-01.2.0', '2015-03-01.1.1', and
'2014-10-01.1.0'.
So try specifying '2016-07-01.3.1'

generateSharedAccessSignature not adding sv parameter?

I'm trying to generate a Shared Access Signature and am using the code here (http://blogs.msdn.com/b/brunoterkaly/archive/2014/06/13/how-to-provision-a-shared-access-signatures-that-allows-clients-to-upload-files-to-to-azure-storage-using-node-js-inside-of-azure-mobile-services.aspx) for a custom API to generate the SAS.
It seems to be missing the sv=2014-02-14 parameter when calling "generateSharedAccessSignature()".
The SAS url doesn't seem to work when I try it (getting a 400 xml not valid error) but if I try a SAS generated from Azure Management Studio the URL contains the "sv" parameter and works when I attempt to upload with it.
Any ideas?
Based on the Storage Service REST API Documentation, sv parameter in Shared Access Signature is introduced in storage service version 2014-02-14. My guess is that Azure Mobile Service is using an older version of the storage service API and this is the reason you don't see sv parameter in your SAS token.
You could be getting 400 error (invalid XML) because of this. In the earlier version of storage service API, the XML syntax for committing block list was different than what is used currently. I have had one more user come to my blog post complaining about the same error. Please try the following XML syntax when performing a commit block list operation and see if the error is gone:
<?xml version="1.0" encoding="utf-8"?>
<BlockList>
<Block>[base64-encoded-block-id]</Block>
<Block>[base64-encoded-block-id]</Block>
...
<Block>[base64-encoded-block-id]</Block>
</BlockList>
Please notice that we're not using Latest node. Instead we're using Block node.
Leaving the sv parameter out and setting it as part of the PUT request header worked using:
xhr.setRequestHeader('x-ms-version','2014-02-14');
You can check out this example for an azure file upload script: http://gauravmantri.com/2013/02/16/uploading-large-files-in-windows-azure-blob-storage-using-shared-access-signature-html-and-javascript/
...which will work with the generated SAS from the question's original blog link - http://blogs.msdn.com/b/brunoterkaly/archive/2014/06/13/how-to-provision-a-shared-access-signatures-that-allows-clients-to-upload-files-to-to-azure-storage-using-node-js-inside-of-azure-mobile-services.aspx
Add the request header in the beforeSend like so:
beforeSend: function(xhr) {
xhr.setRequestHeader('x-ms-version','2014-02-14');
},

Resources