I am having trouble with the getting the correct response for a Python Query on Google App Engine.
Here is the LOG from GAE, it successfully prints out the object that matches the query parameters, but now I am trying to send that objects data as JSON back. I am creating a rudimentary user auth system that queries for a USER object using email and password, and if it exists than it returns all the data back.
How can I break down this query to return the data that was found?
E 00:21:06.352 Encountered unexpected error from ProtoRPC method implementation: AttributeError ('list' object has no attribute 'email')
Traceback (most recent call last):
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/protorpc-1.0/protorpc/wsgi/service.py", line 181, in protorpc_service_app
response = method(instance, request)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/endpoints-1.0/endpoints/api_config.py", line 1332, in invoke_remote
return remote_method(service_instance, request)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/protorpc-1.0/protorpc/remote.py", line 412, in invoke_remote_method
response = method(service_instance, request)
File "/base/data/home/apps/s~caramel-theory-800/1.381271940209425490/photoswap_api.py", line 34, in user_auth
return UserCreateResponseMessage(email=query.email, password=query.password, username=query.username,
AttributeError: 'list' object has no attribute 'email'
E 00:21:06.360 [User(key=Key('User', 5086441721823232), email=u'pop', password=u'top', username=u'yop')]
Here is the ENDPOINT API
I believe the issue is within the last line of code where it trys to return the results of the query (UserAuthResponseMessage)..
#endpoints.method(UserAuthRequestMessage, UserAuthResponseMessage,
path='user', http_method='GET',
name='user.auth')
def user_auth(self, request):
# create some type of query to check for email address, and than check to see if passwords match
query = User.query(User.email == request.email, User.password == request.password).fetch()
print query
# return the info from the server
return UserCreateResponseMessage(email=query[0].email, password=query[0].password, username=query[0].username,
id=query[0].key.id())
APPLICATION = endpoints.api_server([PhotoswapAPI], restricted=False)
You problem is your are performing a query and expecting to reference the email property of the query which of course it doesn't have one.
If you expect only one result from the query then you should be using get rather than index addressing.
The other problem is the user_auth method included doesn't match your stack trace. So there is a problem here.
With the help of Tim Hoffman this is the solution that I was able to come up with.
I was returning the wrong ResponseMessage, and I was better off using .get instead of .fetch as there should only be 1 result returned.
#endpoints.api(name='photoswap', version='v1')
class PhotoswapAPI(remote.Service):
#endpoints.method(UserCreateRequestMessage, UserCreateResponseMessage,
path='user', http_method='POST',
name='user.create')
def user_create(self, request):
entity = User(email=request.email, password=request.password, username=request.username)
entity.put()
return UserCreateResponseMessage(email=entity.email, password=entity.password, username=entity.username,
id=entity.key.id())
#endpoints.method(UserAuthRequestMessage, UserAuthResponseMessage,
path='user', http_method='GET',
name='user.auth')
def user_auth(self, request):
# create some type of query to check for email address, and than check to see if passwords match
query = User.query(User.email == request.email, User.password == request.password).get()
print query
# return the info from the server
return UserAuthResponseMessage(email=query.email, password=query.password, username=query.username, id=query.key.id())
APPLICATION = endpoints.api_server([PhotoswapAPI], restricted=False)
Related
I have some user response data that is posted from the front end to my /post end route and then one piece of that data (user id) is posted to another flask route /stats. That is working properly, when I print to the console I am getting the correct user_id I want to get. The problem is that in this /stats end route I am performing a query of the database to gather some important stats and then I am grabbing those on the front end through a get request. The problem is that when I perform the get request, the state of my request_data is lost and throws the error:
line 67, in stats
user = request_data['user']
TypeError: 'NoneType' object is not subscriptable
the app works perfectly until I perform the get request. here is my code for the flask route /stats:
#app.route('/stats', methods=['GET', 'POST'])
def stats():
request_data = request.get_json()
user = request_data['user']
def get_total_percent_correct(user_id):
correct = d.db_query('SELECT COUNT(*) FROM cards.responses WHERE guess = answer AND user_id = %s' % user_id)
total = d.db_query('SELECT COUNT(*) FROM cards.responses WHERE user_id = %s' % user_id)
return float(correct[0][0])/float(total[0][0])
response_body = {
"stat": get_total_percent_correct(user_id=0),
"user" : user
}
print(get_total_percent_correct(user_id=0))
print(request_data['user'])
return response_body
I would just make 2 if statements for get and post but the problem is I need the user object for my query data. right now the user_id is hardcoded in as 0 but I want to replace that with user object. I appreciate any help. thanks!
I want to implement an email verification in my django app so, I am using an external module verify_email in that there is a function called verify_email() to check whether an entered email address exists or not. In my view.py file I am checking if the mail is valid then a user is created but, the problem is the function verify_email() takes some time to get the result. I think we need to use some kind of await statement to wait for the result but I am getting errors like this when I try to use it normally.
This is the pypi project link.
def register(request):
if(request.method == 'POST'):
email = request.POST['email']
password = request.POST['pass']
username = request.POST['username']
check = verify_email(email)
if check:
user = User.objects.create_user(username,email,password)
user.save()
return redirect('/')
else:
messages.info(request,'email invalid')
return redirect('register')
Description of the error:
Environment:
Request Method: POST
Request URL: http://127.0.0.1:8000/accounts/register/
Django Version: 3.2.3
Python Version: 3.8.5
Traceback (most recent call last):
File "/home/akshith/.local/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/home/akshith/.local/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/akshith/Desktop/django-app/testing/final (copy)/accounts/views.py", line 55, in register
check = verify_email(email)
File "/home/akshith/.local/lib/python3.8/site-packages/verify_email/verify_email.py", line 103, in verify_email
loop = asyncio.get_event_loop()
File "/usr/lib/python3.8/asyncio/events.py", line 639, in get_event_loop
raise RuntimeError('There is no current event loop in thread %r.'
Exception Type: RuntimeError at /accounts/register/
Exception Value: There is no current event loop in thread 'Thread-1'.
Is there a way to use asyncio or any other ways to deal with this kind of error?
Do you really think that the user should proceed even without email verification ?
It usually takes atleast few seconds to verify email on any website, So that should not be a problem. And for Concurrent requests you don't need to worry because django handles them very efficiently.
And sorry, I didn't had enough reputation to comment :)
I am using python to automate JIRA process, while doing I am unable to update Assignee and Comment fields.
While updating Assignee field, not getting any error, but the value is not updated properly, I am trying to assign from one user to other user, but it is getting updated as Unassigned
For comment field, getting an error.
Below is my code:
from atlassian import Jira
jira_instance = Jira(
url = "https://****.atlassian.net/",
username = "****#gmail.com",
password = "*******",
)
data = jira_instance.jql("project = PROJECTNAME AND status = 'IN PROGRESS' ORDER BY created ASC", fields=['description','assignee','reporter','comment'])
for i in range(len(data["issues"])):
test_data = data["issues"][i]
jira_instance.issue_update(test_data['key'], fields={'assignee':{'emailAddress': '#####gmail.com' }})
jira_instance.issue_update(test_data['key'], fields={'comment':{'comments': [{'body':'This is the comment'}]}})
Also tried using displayName instead of using emailAddress, but still same thing happens.
For comment field, got the below error:
Traceback (most recent call last):
File "c:/Users/path/jiratest.py", line 13, in <module>
jira_instance.issue_update(test_data['key'], fields={'comment':{'comments': [{'body':'This is the comment'}]}})
File "C:\Users\path\AppData\Local\Programs\Python\Python37\lib\site-packages\atlassian\jira.py", line 891, in issue_update
return self.put(url, data={"fields": fields})
File "C:\Users\path\AppData\Local\Programs\Python\Python37\lib\site-packages\atlassian\rest_client.py", line 341, in put
absolute=absolute,
File "C:\Users\path\AppData\Local\Programs\Python\Python37\lib\site-packages\atlassian\rest_client.py", line 236, in request
self.raise_for_status(response)
File "C:\Users\path\AppData\Local\Programs\Python\Python37\lib\site-packages\atlassian\jira.py", line 3705, in raise_for_status
raise HTTPError(error_msg, response=response)
requests.exceptions.HTTPError
Please anyone help me out on this
You haven't said if you're using Jira Cloud or Server.
For Jira Cloud, you must set the assignee for an issue using that person's account ID, not their username or email address, so the request would look something like:
jira_instance.issue.update(assignee={'accountId': '5b10ac8d82e05b22cc7d4ef5'})
For adding a comment field, try something like this:
jira_instance.issue_add_comment(test_data['key'], 'This is the comment')
For updating the assignee, try this:
jira_instance.update_issue_field(test_data['key'], fields={"assignee": "####"})
I'm making a web app in python using the Flask framework to request the access token from Facebook using the SDK supplied in their site.
The access token is returned and it is correctly set in the GraphAPI object. However, it is returning the following error:
GraphAPIError: Invalid OAuth access token.
If I query the graph API from my local python environment using the same access token, it works just fine. The problem seems to be when executing in the webserver.
See code snippet below:
#app.route('/facebook')
def fb():
if 'token' in session:
graph = facebook.GraphAPI(session['token'])
return graph.get_object("me")
#app.route('/facebook/login')
def fblogin():
code = request.args.get('code','')
if(code == ""):
args = dict(client_id=app_id, redirect_uri=request.base_url)
#args = dict(client_id=app_id, redirect_uri=request.url_root + 'facebook')
return redirect(
"https://graph.facebook.com/oauth/authorize?" +
urllib.urlencode(args))
else:
token = facebook.get_access_token_from_code(code, request.base_url, app_id, app_secret)
session['token'] = [token.itervalues().next()]
return redirect (request.url_root + 'facebook')
Has anyone faced this before and/or can provide some insights?
Ok, 2 issues that I have managed to correct in this code and get it working:
1) The following line of code makes a list, that why the GraphAPI object is not able to identify a valid access token:
session['token'] = [token.itervalues().next()]
2) The following line of code gives an error stating that 'dict' is not callable. This is because the returned variable is a dictionary and, in order to be returned as a view, one must first transform it into a string:
return graph.get_object("me")
I am trying to read a spreadsheet from app engine using text_db and authsub.
I read http://code.google.com/appengine/articles/gdata.html and got it to work. Then I read http://code.google.com/p/gdata-python-client/wiki/AuthSubWithTextDB and I tried to merge the two in the file below (step4.py) but when I run it locally I get:
Traceback (most recent call last):
File "/home/jmvidal/share/progs/googleapps/google_appengine/google/appengine/ext/webapp/__init__.py", line 498, in __call__
handler.get(*groups)
File "/home/jmvidal/share/progs/googleapps/google_appengine/glassboard/step4.py", line 56, in get
session_token = client._GetDocsClient().UpgradeToSessionToken(auth_token) #If I don't pass this argument I get a NonAuthSubToken
File "/home/jmvidal/share/progs/googleapps/google_appengine/glassboard/gdata/service.py", line 866, in UpgradeToSessionToken
self.SetAuthSubToken(self.upgrade_to_session_token(token))
File "/home/jmvidal/share/progs/googleapps/google_appengine/glassboard/gdata/service.py", line 885, in upgrade_to_session_token
headers={'Content-Type':'application/x-www-form-urlencoded'})
File "/home/jmvidal/share/progs/googleapps/google_appengine/glassboard/gdata/auth.py", line 678, in perform_request
return http_client.request(operation, url, data=data, headers=headers)
File "/home/jmvidal/share/progs/googleapps/google_appengine/glassboard/atom/http.py", line 163, in request
return connection.getresponse()
File "/home/jmvidal/share/progs/googleapps/google_appengine/google/appengine/dist/httplib.py", line 200, in getresponse
self._allow_truncated, self._follow_redirects)
File "/home/jmvidal/share/progs/googleapps/google_appengine/google/appengine/api/urlfetch.py", line 267, in fetch
raise DownloadError(str(e))
DownloadError: ApplicationError: 2 nonnumeric port: ''
Can anyone shed some light on this? Specifically, why is it that the original (step3.py from the first link) works but my call here to UpgradeToSessionToken fails?
# step4.py
#
# Trying to read spreadsheets from app engine using text_db and authsub.
#
# Merge of this code
# http://code.google.com/p/gdata-python-client/wiki/AuthSubWithTextDB
# with this one
# http://code.google.com/appengine/articles/gdata.html (step 3)
import wsgiref.handlers
import cgi
from google.appengine.ext import webapp
from google.appengine.api import users
import atom.url
import gdata.service
import gdata.alt.appengine
import gdata.spreadsheet.text_db
import settings
class Fetcher(webapp.RequestHandler):
def get(self):
# Write our pages title
self.response.out.write("""<html><head><title>
Google Data Feed Fetcher: read Google Data API Atom feeds</title>""")
self.response.out.write('</head><body>')
next_url = atom.url.Url('http', settings.HOST_NAME, path='/step4')
# Allow the user to sign in or sign out
if users.get_current_user():
self.response.out.write('Sign Out<br>' % (
users.create_logout_url(str(next_url))))
else:
self.response.out.write('Sign In<br>' % (
users.create_login_url(str(next_url))))
# Initialize a client to talk to Google Data API services.
# client = gdata.service.GDataService()
# auth_url = client.GenerateAuthSubURL(
# next_url,
# ('http://docs.google.com/feeds/',), secure=False, session=True)
client = gdata.spreadsheet.text_db.DatabaseClient()
auth_url = client._GetDocsClient().GenerateAuthSubURL(
next_url,
('http://spreadsheets.google.com/feeds/','http://docs.google.com/feeds/documents/'), secure=False, session=True)
gdata.alt.appengine.run_on_appengine(client)
feed_url = self.request.get('feed_url')
session_token = None
# Find the AuthSub token and upgrade it to a session token.
auth_token = gdata.auth.extract_auth_sub_token_from_url(self.request.uri)
if auth_token:
# Upgrade the single-use AuthSub token to a multi-use session token.
client._GetDocsClient().SetAuthSubToken(auth_token)
session_token = client._GetDocsClient().UpgradeToSessionToken(auth_token) #If I don't pass this argument I get a NonAuthSubToken
client._GetSpreadsheetsClient().SetAuthSubToken(client._GetDocsClient().GetAuthSubToken())
# session_token = client.upgrade_to_session_token(auth_token)
if session_token and users.get_current_user():
# If there is a current user, store the token in the datastore and
# associate it with the current user. Since we told the client to
# run_on_appengine, the add_token call will automatically store the
# session token if there is a current_user.
client.token_store.add_token(session_token)
elif session_token:
# Since there is no current user, we will put the session token
# in a property of the client. We will not store the token in the
# datastore, since we wouldn't know which user it belongs to.
# Since a new client object is created with each get call, we don't
# need to worry about the anonymous token being used by other users.
client.current_token = session_token
self.response.out.write('<div id="main">')
self.fetch_feed(client, feed_url)
self.response.out.write('</div>')
self.response.out.write(
'<div id="sidebar"><div id="scopes"><h4>Request a token</h4><ul>')
self.response.out.write('<li>Google Documents</li>' % (auth_url))
self.response.out.write('</ul></div><br/><div id="tokens">')
def fetch_feed(self, client, feed_url):
# Attempt to fetch the feed.
if not feed_url:
self.response.out.write(
'No feed_url was specified for the app to fetch.<br/>')
example_url = atom.url.Url('http', settings.HOST_NAME, path='/step4',
params={'feed_url':
'http://docs.google.com/feeds/documents/private/full'}
).to_string()
self.response.out.write('Here\'s an example query which will show the'
' XML for the feed listing your Google Documents <a '
'href="%s">%s</a>' % (example_url, example_url))
return
try:
response = client.Get(feed_url, converter=str)
self.response.out.write(cgi.escape(response))
except gdata.service.RequestError, request_error:
# If fetching fails, then tell the user that they need to login to
# authorize this app by logging in at the following URL.
if request_error[0]['status'] == 401:
# Get the URL of the current page so that our AuthSub request will
# send the user back to here.
next = atom.url.Url('http', settings.HOST_NAME, path='/step4',
params={'feed_url': feed_url})
# If there is a current user, we can request a session token, otherwise
# we should ask for a single use token.
auth_sub_url = client.GenerateAuthSubURL(next, feed_url,
secure=False, session=True)
self.response.out.write('<a href="%s">' % (auth_sub_url))
self.response.out.write(
'Click here to authorize this application to view the feed</a>')
else:
self.response.out.write(
'Something went wrong, here is the error object: %s ' % (
str(request_error[0])))
def main():
application = webapp.WSGIApplication([('/.*', Fetcher),], debug=True)
wsgiref.handlers.CGIHandler().run(application)
if __name__ == '__main__':
main()
As always, I figure out the answer only after giving up and asking for help.
we need to add two more calls to run_on_appengine (to register the two clients that the text_db client has):
gdata.alt.appengine.run_on_appengine(client)
gdata.alt.appengine.run_on_appengine(client._GetDocsClient())
gdata.alt.appengine.run_on_appengine(client._GetSpreadsheetsClient()) here
I would have expected the first call to run_on_appengine to result in the two other calls, but I guess not.
Oh, and change the auth_url line to:
auth_url = client._GetDocsClient().GenerateAuthSubURL(
next_url,scope='http://spreadsheets.google.com/feeds/ http://docs.google.com/feeds/documents/', secure=False, session=True)
Passing the scope urls in a list caused a "token does not have the correct scope" error.