How to integrate gspread with aiohttp - python-asyncio

I am trying to use gspread, but I need the library to mesh well with another async library I am using.
After digging through the docs for gspread, I found this function that I can use:
class gspread.Client(auth, session=None)
An instance of this class communicates with Google API.
Parameters:
auth – An OAuth2 credential object. Credential objects are those created by the oauth2client library. https://github.com/google/oauth2client
session – (optional) A session object capable of making HTTP requests while persisting some parameters across requests. Defaults to requests.Session.
Which gives me an optional session parameter. How would I specify the session to use aiohttp?
I wrote a bit of test code, which compiles fine, but running the code crashes.
import aiohttp
import gspread
import random
from oauth2client.service_account import ServiceAccountCredentials
scope = ['https://spreadsheets.google.com/feeds',
'https://www.googleapis.com/auth/drive']
creds = ServiceAccountCredentials.from_json_keyfile_name('client_secret.json', scope)
c = gspread.authorize(creds)
client = gspread.Client(auth=c, session=aiohttp.ClientSession)
sheet = client.open_by_key('1Hkwo9gSpk3NjgPLPkG8kh0zBNw2nxsYWRw0cVdn0JA0')
ws = sheet.get_worksheet(0)
rcount = ws.row_count
msg = ws.cell(random.randint(1,rcount),1).value
print(msg)
The error message I get is below:
Traceback (most recent call last):
File "c:\Users\xxxxx\.vscode\extensions\ms-python.python-2018.9.0\pythonFiles\experimental\ptvsd_launcher.py", line 118, in <module>
vspd.debug(filename, port_num, '', '', run_as)
File "c:\Users\xxxxx\.vscode\extensions\ms-python.python-2018.9.0\pythonFiles\experimental\ptvsd\ptvsd\debugger.py", line 37, in debug
run(address, filename, *args, **kwargs)
File "c:\Users\xxxxx\.vscode\extensions\ms-python.python-2018.9.0\pythonFiles\experimental\ptvsd\ptvsd\_local.py", line 79, in run_file
run(argv, addr, **kwargs)
File "c:\Users\xxxxx\.vscode\extensions\ms-python.python-2018.9.0\pythonFiles\experimental\ptvsd\ptvsd\_local.py", line 140, in _run
_pydevd.main()
File "c:\Users\xxxxx\.vscode\extensions\ms-python.python-2018.9.0\pythonFiles\experimental\ptvsd\ptvsd\_vendored\pydevd\pydevd.py", line 1751, in main
debugger.connect(host, port)
File "c:\Users\xxxxx\.vscode\extensions\ms-python.python-2018.9.0\pythonFiles\experimental\ptvsd\ptvsd\_vendored\pydevd\pydevd.py", line 1107, in run
return self._exec(is_module, entry_point_fn, module_name, file, globals, locals)
File "c:\Users\xxxxx\.vscode\extensions\ms-python.python-2018.9.0\pythonFiles\experimental\ptvsd\ptvsd\_vendored\pydevd\pydevd.py", line 1114, in _exec
pydev_imports.execfile(file, globals, locals) # execute the script
File "c:\Users\xxxxx\.vscode\extensions\ms-python.python-2018.9.0\pythonFiles\experimental\ptvsd\ptvsd\_vendored\pydevd\_pydev_imps\_pydev_execfile.py", line 25, in execfile
exec(compile(contents+"\n", file, 'exec'), glob, loc)
File "c:\Users\xxxxx\Desktop\Coding\Discord Bot\Testing\test.py", line 14, in <module>
ws = sheet.get_worksheet(0)
File "C:\Users\xxxxx\AppData\Local\Programs\Python\Python36\lib\site-packages\gspread\models.py", line 141, in get_worksheet
sheet_data = self.fetch_sheet_metadata()
File "C:\Users\xxxxx\AppData\Local\Programs\Python\Python36\lib\site-packages\gspread\models.py", line 123, in fetch_sheet_metadata
r = self.client.request('get', url, params=params)
File "C:\Users\xxxxx\AppData\Local\Programs\Python\Python36\lib\site-packages\gspread\client.py", line 73, in request
headers=headers
TypeError: get() missing 1 required positional argument: 'url'
PS C:\Users\xxxxx\Desktop\Coding\Discord Bot>
Any ideas?

It's impossible to use aiohttp with current version of gspread (3.0.1). the gspread library uses synchronous calls and aiohttp uses asynchronous calls.
Please, reconsider to use compatible library like requests or httplib2.

For anyone wondering, once I posted this question, I found that someone made an async wrapper for gspread. Check out the library here and show this guy your appreciation. I sure am!

Related

StatusCode.UNIMPLEMENTED when making Vertex AI API call

I have a simple Python app that invokes a Vertex AI API that fails when it runs and I can't understand why. The application is as follows:
from google.cloud import aiplatform_v1
def sample_list_datasets():
client = aiplatform_v1.DatasetServiceClient()
request = aiplatform_v1.ListDatasetsRequest(
parent="projects/MYPROJECT/locations/us-central1",
)
page_result = client.list_datasets(request=request)
for response in page_result:
print(response)
sample_list_datasets()
when run, it fails with:
E0126 03:52:04.146970105 22462 hpack_parser.cc:1218] Error parsing metadata: error=invalid value key=content-type value=text/html; charset=UTF-8
Traceback (most recent call last):
File "/home/kolban/projects/vertex-ai/datasets/env/lib/python3.7/site-packages/google/api_core/grpc_helpers.py", line 72, in error_remapped_callable
return callable_(*args, **kwargs)
File "/home/kolban/projects/vertex-ai/datasets/env/lib/python3.7/site-packages/grpc/_channel.py", line 946, in __call__
return _end_unary_response_blocking(state, call, False, None)
File "/home/kolban/projects/vertex-ai/datasets/env/lib/python3.7/site-packages/grpc/_channel.py", line 849, in _end_unary_response_blocking
raise _InactiveRpcError(state)
grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
status = StatusCode.UNIMPLEMENTED
details = "Received http2 header with status: 404"
debug_error_string = "UNKNOWN:Error received from peer ipv4:108.177.120.95:443 {created_time:"2023-01-26T03:52:04.147076255+00:00", grpc_status:12, grpc_message:"Received http2 header with status: 404"}"
>
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "run.py", line 25, in <module>
sample_list_datasets()
File "run.py", line 19, in sample_list_datasets
page_result = client.list_datasets(request=request)
File "/home/kolban/projects/vertex-ai/datasets/env/lib/python3.7/site-packages/google/cloud/aiplatform_v1/services/dataset_service/client.py", line 1007, in list_datasets
metadata=metadata,
File "/home/kolban/projects/vertex-ai/datasets/env/lib/python3.7/site-packages/google/api_core/gapic_v1/method.py", line 113, in __call__
return wrapped_func(*args, **kwargs)
File "/home/kolban/projects/vertex-ai/datasets/env/lib/python3.7/site-packages/google/api_core/grpc_helpers.py", line 74, in error_remapped_callable
raise exceptions.from_grpc_error(exc) from exc
google.api_core.exceptions.MethodNotImplemented: 501 Received http2 header with status: 404
What might I be doing wrong?
Changing the code to the following caused it to work:
from google.cloud import aiplatform_v1
from google.api_core.client_options import ClientOptions
def sample_list_datasets():
service_base_path='aiplatform.googleapis.com'
region='us-central1'
client_options = ClientOptions(api_endpoint=f"{region}-{service_base_path}")
client = aiplatform_v1.DatasetServiceClient(client_options=client_options)
request = aiplatform_v1.ListDatasetsRequest(
parent="projects/MYPROJECT/locations/us-central1",
)
# Make the request
page_result = client.list_datasets(request=request)
# Handle the response
for response in page_result:
print(response)
sample_list_datasets()
The resolution was hinted at in the documentation for the API request found here. At that article there is a code sample and in the code sample there are some comments and in the comments the following is written:
It may require specifying regional endpoints when creating the service
client as shown in:
https://googleapis.dev/python/google-api-core/latest/client_options.html
And this was the core clue. When we make Vertex AI calls we must specify where the request is to be sent. We do this by setting the api_endpoint option to a URL of the form [REGION]-aiplatform.googleapis.com.

How do you get the main "function" of a command in discord.py?

I'm trying to create a command that sends the code of another command in discord.py. For example, if I had a command for rock paper scissors and i ran .code rps, It would send the code for the rps command. Here is my code so far:
import inspect
import discord
from discord.ext.commands import Bot, cooldown, BucketType, CommandOnCooldown
from discord.ext import commands, tasks
#bot.command(hidden=True)
#commands.is_owner()
async def code(ctx, *, command_name):
"""Sends code of a command"""
com = bot.get_command(command_name)
if com is None:
await ctx.reply(f"Bruh that isn't a command", mention_author=False)
elif com:
source = inspect.getsource(com)
try:
await ctx.reply(f"```\n{source}\n```", mention_author=False)
except discord.HTTPException:
await ctx.reply(f"That command's code is too long for me to send lmao", mention_author=False)
print(source)
But there's an error because it can't find the source code of a command type
Ignoring exception in command code:
Traceback (most recent call last):
File "/Users/Bello/PycharmProjects/larry/venv3.8/lib/python3.8/site-packages/discord/ext/commands/core.py", line 85, in wrapped
ret = await coro(*args, **kwargs)
File "/Users/Bello/PycharmProjects/larry/venv3.8/test.py", line 351, in code
source = inspect.getsource(com)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/inspect.py", line 985, in getsource
lines, lnum = getsourcelines(object)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/inspect.py", line 967, in getsourcelines
lines, lnum = findsource(object)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/inspect.py", line 780, in findsource
file = getsourcefile(object)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/inspect.py", line 696, in getsourcefile
filename = getfile(object)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/inspect.py", line 676, in getfile
raise TypeError('module, class, method, function, traceback, frame, or '
TypeError: module, class, method, function, traceback, frame, or code object was expected, got Command
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/Bello/PycharmProjects/larry/venv3.8/lib/python3.8/site-packages/discord/ext/commands/bot.py", line 902, in invoke
await ctx.command.invoke(ctx)
File "/Users/Bello/PycharmProjects/larry/venv3.8/lib/python3.8/site-packages/discord/ext/commands/core.py", line 864, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "/Users/Bello/PycharmProjects/larry/venv3.8/lib/python3.8/site-packages/discord/ext/commands/core.py", line 94, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: module, class, method, function, traceback, frame, or code object was expected, got Command
Is there a way to find the source code of a command object or figure out a loophole that lets me do that? Thanks!!
Simply use the callback attribute
func = com.callback
source = inspect.getsource(func)
Reference:
Command.callback

Error the deployment function in lambda with graphene module

error when executing the function in aws lambda, while locally there is no error.
When executing the code in AWS lambda this error arises, what I want is to be able to use graqpl to perform dynamodb queries and to use them.
Solution attempt: uninstall typing from the python virtual environment.
Error that occurs:
[ERROR] AttributeError: type object 'Callable' has no attribute '_abc_registry'
Traceback (most recent call last):
File "/var/lang/lib/python3.7/imp.py", line 234, in load_module
return load_source(name, filename, file)
File "/var/lang/lib/python3.7/imp.py", line 171, in load_source
module = _load(spec)
File "<frozen importlib._bootstrap>", line 696, in _load
File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 728, in exec_module
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File "/var/task/patron4.py", line 7, in <module>
import graphene
File "/tmp/sls-py-req/graphene/__init__.py", line 3, in <module>
from .types import (
File "/tmp/sls-py-req/graphene/types/__init__.py", line 2, in <module>
from graphql import ResolveInfo
File "/tmp/sls-py-req/graphql/__init__.py", line 27, in <module>
from .graphql import graphql
File "/tmp/sls-py-req/graphql/graphql.py", line 1, in <module>
from .execution import ExecutionResult
File "/tmp/sls-py-req/graphql/execution/__init__.py", line 21, in <module>
from .executor import execute, subscribe
File "/tmp/sls-py-req/graphql/execution/executor.py", line 14, in <module>
from promise import Promise, promise_for_dict, is_thenable
File "/tmp/sls-py-req/promise/__init__.py", line 18, in <module>
from .promise import (
File "/tmp/sls-py-req/promise/promise.py", line 8, in <module>
from typing import (List, Any, Callable, Dict, Iterator, Optional, # flake8: noqa
File "/tmp/sls-py-req/typing.py", line 1357, in <module>
class Callable(extra=collections_abc.Callable, metaclass=CallableMeta):
File "/tmp/sls-py-req/typing.py",enter code here line 1005, in __new__
self._abc_registry = extra._abc_registry
Code used:
class User(Model):
class Meta:
table_name = 'patron2'
region = 'us-east-2'
host = 'https://dynamodb.us-east-2.amazonaws.com'
id = UnicodeAttribute(hash_key=True, null=False)
discipline = UnicodeAttribute(null=False)
class UserNode(PynamoObjectType):
class Meta:
model = User
interfaces = (graphene.Node,)
class Query(graphene.ObjectType):
users = graphene.List(UserNode)
def resolve_users(self, args, context, info):
return list(User.scan())
schema = graphene.Schema(query=Query)
def patrongrafico(event, context):
# fetch all todos from the database
try:
print("hola")
query = '''
users {
discipline
}
'''
results = schema.execute(query)
print(results)
except Exception as ex:
print(ex)
return {'statusCode': 200,
'body': json.dumps({'items': [dict(result) for result in results]})}
Since you're using the Serverless Framework in combination with the serverless-python-requirements plugin you should make sure, that slim packaging is off, as this interferes with some libraries. Essentially some libraries assume they're installed via a "real" package manager and in that case the directory layout and files look slightly different.
I was having this problem with the jsonschema package a few months ago and wrote about it in a blog post if you're interested (Full disclosure: this is the blog of my employer).
Essentially your serverless.yml as a custom section which you can use among other things to configure the plugins:
custom:
pythonRequirements:
slim: true
The slim true parameter effectively removes some information that shouldn't be necessary for most libraries, but some rely on it. For information on this parameter see the package's docs.
Try again with this configuration:
custom:
pythonRequirements:
slim: false
The solution to the error is to remove the version of Python 3.7 and implement 3.6, since Graphene does not support versions greater than 3.6.

werkzeug server failed to handle request

I'm trying to run this gevent server
from gevent import pywsgi
from Index import application
import paste.urlparser
import os
# http server: serves up static files
print "static files",os.path.dirname(__file__)
print "serving on localhost:8000"
http_server = pywsgi.WSGIServer(
('', 8000),
paste.urlparser.StaticURLParser(os.path.dirname(__file__)))
print 'Serving on https://127.0.0.1:4000'
server = pywsgi.WSGIServer(('0.0.0.0', 4000), application,spawn=None)
# Start the server greenlets
http_server.start()
# to start the server asynchronously, call server.start()
# we use blocking serve_forever() here because we have no other jobs
server.serve_forever()
I'm getting this exception where it gives me failed to handle request from werkzeug server.
I've used only werkzeug utility and have never used werkzeug server..
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/gevent/server.py", line 131, in _do_accept
self._handle(client_socket, address)
File "/usr/local/lib/python2.7/dist-packages/gevent/pywsgi.py", line 571, in handle
handler.handle()
File "/usr/local/lib/python2.7/dist-packages/gevent/pywsgi.py", line 180, in handle
result = self.handle_one_request()
File "/usr/local/lib/python2.7/dist-packages/gevent/pywsgi.py", line 287, in handle_one_request
raw_requestline = self.read_requestline()
File "/usr/local/lib/python2.7/dist-packages/gevent/pywsgi.py", line 280, in read_requestline
return self.rfile.readline(MAX_REQUEST_LINE)
File "/usr/lib/python2.7/socket.py", line 476, in readline
data = self._sock.recv(self._rbufsize)
File "/usr/local/lib/python2.7/dist-packages/gevent/socket.py", line 432, in recv
wait_read(sock.fileno(), timeout=self.timeout, event=self._read_event)
File "/usr/local/lib/python2.7/dist-packages/gevent/socket.py", line 169, in wait_read
switch_result = get_hub().switch()
File "/usr/local/lib/python2.7/dist-packages/gevent/hub.py", line 154, in switch
assert cur is not self, 'Cannot switch to MAINLOOP from MAINLOOP'
AssertionError: Cannot switch to MAINLOOP from MAINLOOP
<WSGIServer fileno=4 address=0.0.0.0:4000>: Failed to handle request from ('127.0.0.1', 36088)

gdata.docs.client.DocsClient

I have the following code, reads oauth2 token form file, then try's to perform a doc's list query to find a specific spreadsheet that I want to copy, however no matter what I try the code either errors out or returns with an object containing no document data.
I am using gdata.docs.client.DocsClient which as far as I can tell is version 3 of the API
def CreateClient():
"""Create a Documents List Client."""
client = gdata.docs.client.DocsClient(source=config.APP_NAME)
client.http_client.debug = config.DEBUG
# Authenticate the user with CLientLogin, OAuth, or AuthSub.
if os.path.exists(config.CONFIG_FILE):
f = open(config.CONFIG_FILE)
tok = pickle.load(f)
f.close()
client.auth_token = tok.auth_token
return client
1st query attempt
def get_doc():
new_api_query = gdata.docs.client.DocsQuery(title='RichSheet', title_exact=True, show_collections=True)
d = client.GetResources(q = new_api_query)
this fails with the following stack trace
Traceback (most recent call last):
File "/Users/richard/PycharmProjects/reportone/make_my_report.py", line 83, in <module>
get_doc()
File "/Users/richard/PycharmProjects/reportone/make_my_report.py", line 57, in get_doc
d = client.GetResources(q = new_api_query)
File "/Users/richard/PycharmProjects/reportone/gdata/docs/client.py", line 151, in get_resources
**kwargs)
File "/Users/richard/PycharmProjects/reportone/gdata/client.py", line 640, in get_feed
**kwargs)
File "/Users/richard/PycharmProjects/reportone/gdata/docs/client.py", line 66, in request
return super(DocsClient, self).request(method=method, uri=uri, **kwargs)
File "/Users/richard/PycharmProjects/reportone/gdata/client.py", line 267, in request
uri=uri, auth_token=auth_token, http_request=http_request, **kwargs)
File "/Users/richard/PycharmProjects/reportone/atom/client.py", line 115, in request
self.auth_token.modify_request(http_request)
File "/Users/richard/PycharmProjects/reportone/gdata/gauth.py", line 1047, in modify_request
token_secret=self.token_secret, verifier=self.verifier)
File "/Users/richard/PycharmProjects/reportone/gdata/gauth.py", line 668, in generate_hmac_signature
next, token, verifier=verifier)
File "/Users/richard/PycharmProjects/reportone/gdata/gauth.py", line 629, in build_oauth_base_string
urllib.quote(params[key], safe='~')))
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib.py", line 1266, in quote
if not s.rstrip(safe):
AttributeError: 'bool' object has no attribute 'rstrip'
Process finished with exit code 1
then my second attempt
def get_doc():
other = gdata.docs.service.DocumentQuery(text_query='RichSheet')
d = client.GetResources(q = other)
this returns an ResourceFeed object, but has no content. I have been through the source code for these function but thing are not any obvious.
Have i missed something ? or should i go back to version 2 of the api ?

Resources