I am trying to use python-twitter api in GAE.
I need to import Oauth2 and httplib2.
Here is how I did
For OAuth2, I downloaded github.com/simplegeo/python-oauth2/tree/master/oauth2. For HTTPLib2, I dowloaded code.google.com/p/httplib2/wiki/Install and extracted folder python2/httplib2 to project root folder.
my views.py
import twitter
def index(request):
api = twitter.Api(consumer_key='XNAUYmsmono4gs3LP4T6Pw',consumer_secret='xxxxx',access_token_key='xxxxx',access_token_secret='iHzMkC6RRDipon1kYQtE5QOAYa1bVfYMhH7GFmMFjg',cache=None)
return render_to_response('fbtwitter/index.html')
I got the error paste.shehas.net/show/jbXyx2MSJrpjt7LR2Ksc
AttributeError
AttributeError: 'module' object has no attribute 'SignatureMethod_PLAINTEXT'
Traceback (most recent call last)
File "D:\PythonProj\fbtwitter\kay\lib\werkzeug\wsgi.py", line 471, in __call__
return app(environ, start_response)
File "D:\PythonProj\fbtwitter\kay\app.py", line 478, in __call__
response = self.get_response(request)
File "D:\PythonProj\fbtwitter\kay\app.py", line 405, in get_response
return self.handle_uncaught_exception(request, exc_info)
File "D:\PythonProj\fbtwitter\kay\app.py", line 371, in get_response
response = view_func(request, **values)
File "D:\PythonProj\fbtwitter\fbtwitter\views.py", line 39, in index
access_token_secret='iHzMkC6RRDipon1kYQtE5QOAYa1bVfYMhH7GFmMFjg',cache=None)
File "D:\PythonProj\fbtwitter\fbtwitter\twitter.py", line 2235, in __init__
self.SetCredentials(consumer_key, consumer_secret, access_token_key, access_token_secret)
File "D:\PythonProj\fbtwitter\fbtwitter\twitter.py", line 2264, in SetCredentials
self._signature_method_plaintext = oauth.SignatureMethod_PLAINTEXT()
AttributeError: 'module' object has no attribute 'SignatureMethod_PLAINTEXT'
It seems I did not import Oauth2 correctly when I tracked the error in twitter.py
self._signature_method_plaintext = oauth.SignatureMethod_PLAINTEXT()
I even go to twitter.py and add import oauth2 as oauth but it couldnt solve the problem
Can anybody help?
I fixed it. In twitter.py,
try:
from hashlib import md5
except ImportError:
from md5 import md5
import oauth
CHARACTER_LIMIT = 140
# A singleton representing a lazily instantiated FileCache.
DEFAULT_CACHE = object()
REQUEST_TOKEN_URL = 'https://api.twitter.com/oauth/request_token'
ACCESS_TOKEN_URL = 'https://api.twitter.com/oauth/access_token'
AUTHORIZATION_URL = 'https://api.twitter.com/oauth/authorize'
SIGNIN_URL = 'https://api.twitter.com/oauth/authenticate'
Need to change import oauth to import oauth2 as oauth
I'm using tweetpy with my GAE application and it works well.
https://github.com/tweepy/tweepy
You can find some sample codes of tweetpy on GAE in google search.
Related
File "/layers/google.python.pip/pip/lib/python3.8/site-packages/django/core/handlers/exception.py", line 55, in inner
response = get_response(request)
File "/layers/google.python.pip/pip/lib/python3.8/site-packages/django/core/handlers/base.py", line 197, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/layers/google.python.pip/pip/lib/python3.8/site-packages/django/views/generic/base.py", line 103, in view
return self.dispatch(request, *args, **kwargs)
File "/layers/google.python.pip/pip/lib/python3.8/site-packages/django/views/generic/base.py", line 142, in dispatch
return handler(request, *args, **kwargs)
File "/workspace/apps/account/views.py", line 235, in post
taskqueue.add(queue_name='create-waybill', url = reverse('_api:createWaybill') , params = {'key':url_key})
File "/layers/google.python.pip/pip/lib/python3.8/site-packages/google/appengine/api/taskqueue/taskqueue.py", line 575, in create_rpc
return apiproxy_stub_map.UserRPC('taskqueue', deadline, callback)
File "/layers/google.python.pip/pip/lib/python3.8/site-packages/google/appengine/api/apiproxy_stub_map.py", line 444, in __init__
self.__rpc = CreateRPC(service, stubmap)
File "/layers/google.python.pip/pip/lib/python3.8/site-packages/google/appengine/api/apiproxy_stub_map.py", line 69, in CreateRPC
assert stub, 'No api proxy found for service "%s"' % service
AssertionError: No api proxy found for service "taskqueue"
I am working on google app engine and try to run taskqueue and getting error
i am using django python3
from google.appengine.api import taskqueue
taskqueue.Task(name='create-waybill', url='/_api/createWaybill',params = {'key':url_key}).add()
just this one
and
path ('createWaybill', csrf_exempt(views.CreateWaybill.as_view()), name='createWaybill'),
To use the bundled services in Python 3, you first have to enable them.
See documentation from Google for doing that
When running the following minimal code to execute the GMail API watch() method. A 'Backend Error' occurs. This is true both when running on a client machine, and when run directly on Google Cloud as a Cloud Function.
from google.oauth2 import service_account
import googleapiclient.discovery
SCOPES = ["https://mail.google.com/"]
SERVICE_ACCOUNT_FILE = '<JSON KEY FILE REMOVED>'
TARGET='<GSUITE DOMAIN USER EMAIL ADDRESS>'
credentials = service_account.Credentials.from_service_account_file(SERVICE_ACCOUNT_FILE, scopes=SCOPES)
credentials_delegated = credentials.with_subject(TARGET)
service = googleapiclient.discovery.build('gmail', 'v1', credentials=credentials_delegated)
val = { 'topicName': '<TOPIC NAME COPIED FROM GCLOUD PUB/SUB>' }
watch_resp = service.users().watch(userId='me', body=val).execute()
print(watch_resp)
Other GMail APIs such as service.users().getProfile(userId='me').execute() work as expected. This error occurs after ensuring that the service account and the delegated user have the pub/sub publisher role and that the topic name is correct and already created. The exact output of the error is as follows:
Traceback (most recent call last):
File "test.py", line 12, in <module>
watch_resp = service.users().watch(userId='me', body=val).execute()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/googleapiclient/_helpers.py", line 130, in positional_wrapper
return wrapped(*args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/googleapiclient/http.py", line 842, in execute
raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 500 when requesting https://www.googleapis.com/gmail/v1/users/me/watch?alt=json returned "Backend Error">
Use the example code from app engine will give an attribute error. The more strange thing is,
When the batch_size is 100, the first fetch will give an error while if it were set to 10, the second fetch will give the error, when the batch_size is 1, the 25th fetch will give the error. Is it due to the problem of remote API?
Python version: 2.7
App engine sdk version: 1.9.6
query = MyModel.all()
entities = query.fetch(100)
while entities:
for entity in entities:
# Do something with entity
query.with_cursor(query.cursor())
entities = query.fetch(100)
error message:
Traceback (most recent call last):
File "migrate.py", line 77, in <module>
entities = query.fetch(batch_size)
File "/home/kamel/Library/google_appengine/google/appengine/ext/db/__init__.py", line 2157, in fetch
return list(self.run(limit=limit, offset=offset, **kwargs))
File "/home/kamel/Library/google_appengine/google/appengine/ext/db/__init__.py", line 2326, in next
return self.__model_class.from_entity(self.__iterator.next())
File "/home/kamel/Library/google_appengine/google/appengine/ext/db/__init__.py", line 1435, in from_entity
entity_values = cls._load_entity_values(entity)
File "/home/kamel/Library/google_appengine/google/appengine/ext/db/__init__.py", line 1413, in _load_entity_values
value = prop.make_value_from_datastore(value)
File "/home/kamel/labola/src/model/properties.py", line 295, in make_value_from_datastore
return pickle.loads(value)
File "/usr/lib/python2.7/pickle.py", line 1382, in loads
return Unpickler(file).load()
File "/usr/lib/python2.7/pickle.py", line 858, in load
dispatch[key](self)
File "/usr/lib/python2.7/pickle.py", line 1083, in load_newobj
obj = cls.__new__(cls, *args)
AttributeError: class Reference has no attribute '__new__
I encountered the same issue when trying to unpickle python3 pickles under python2. The problem was linked to new-style classes becoming default in python3. (source)
Solution for me was to replace class AClass: by class AClass(object):
I read the "what is a metaclass in Python" but am still confused over it.
I am new to python and have been thrown into upgrading it from 2.5 to 2.7.
I have the following:
class UsersDB(db.Model):
Email = db.EmailProperty(required=True,verbose_name='Email *')
Enable = db.BooleanProperty(default=True)
and
class UsersQuickAddForm(forms.ModelForm):
def is_user_exist(self, account):
users_query = UsersDB.all().filter('Email =', account).fetch(1)
if len(users_query) > 0:
return True
return False
class Meta:
model = UsersDB
exclude = ['Enable']
but when I try to execute it on the google site, I get:
Traceback (most recent call last):
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/runtime/wsgi.py", line 239, in Handle
handler = _config_handle.add_wsgi_middleware(self._LoadHandler())
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/runtime/wsgi.py", line 298, in _LoadHandler
handler, path, err = LoadObject(self._handler)
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/runtime/wsgi.py", line 84, in LoadObject
obj = import(path[0])
File "/base/data/home/apps/s~ldsdgidev/glen27.371429613087607751/LDSGH.py", line 8, in
from core.decorators import permissionRequired
File "/base/data/home/apps/s~ldsdgidev/glen27.371429613087607751/core/decorators.py", line 7, in
from core.initialization import loginIf
File "/base/data/home/apps/s~ldsdgidev/glen27.371429613087607751/core/initialization.py", line 6, in
import photo_images
File "/base/data/home/apps/s~ldsdgidev/glen27.371429613087607751/core/photo_images.py", line 1, in
from core.db_models import ImagesDB
File "/base/data/home/apps/s~ldsdgidev/glen27.371429613087607751/core/db_models.py", line 222, in
class UsersQuickAddForm(forms.ModelForm):#only account, firstname and last name is required
File "/base/data/home/apps/s~ldsdgidev/glen27.371429613087607751/django/forms/models.py", line 205, in new
opts.exclude, opts.widgets, formfield_callback)
File "/base/data/home/apps/s~ldsdgidev/glen27.371429613087607751/django/forms/models.py", line 145, in fields_for_model
opts = model._meta
AttributeError: type object 'UsersDB' has no attribute '_meta'
and I don't understand what I need to add to the UserDB class to get rid of the error.
Any help would be great!
This isn't anything to do with Python versions, or metaclasses.
ModelForms only work with Django models. db.Model is the App Engine model class, not the Django one. You can't use a modelform with that class.
You mention django-nonrel in your question tags. That project allows you to use the Django models - subclasses of models.Model with the App Engine datastore. You probably want to do that.
I try a simple HelloWorld with gdata, appengine and OAuth2. I read this post and the official post from Google.
Problem 1
According to the first post post, my app fails at the part 7 "Use the code to get an access token" :
Traceback (most recent call last):
File "[$PATH]/dev/outils/google_appengine/google/appengine/ext/webapp/_webapp25.py", line 701, in __call__
handler.get(*groups)
File "[$PATH]/dev/outils/google_appengine/google/appengine/ext/webapp/util.py", line 68, in check_login
handler_method(self, *args)
File "[$PATH]/dev/projets/xxx/main.py", line 76, in get
token.get_access_token(url.query)
File "[$PATH]/dev/projets/xxx/gdata/gauth.py", line 1296, in get_access_token
'redirect_uri': self.redirect_uri,
AttributeError: 'OAuth2Token' object has no attribute 'redirect_uri'
I provide the redirect_uri in the method generate_authorize_url() and i filled 2 "Redirect URIs" on Google APIs console :
http://localhost:8080/oauth2callback
http://example.com/oauth2callback
Why the redirect_uri is loosed ?
Solution : See #bossylobster answer.
Problem 2
Now, i want to save this new access token like this :
access_token_key = 'access_token_%s' % current_user.user_id()
gdata.gauth.ae_save(token, access_token_key)
Theses lines throw this exception :
Traceback (most recent call last):
File "[$PATH]/dev/outils/google_appengine/google/appengine/ext/webapp/_webapp25.py", line 701, in __call__
handler.get(*groups)
File "[$PATH]/dev/outils/google_appengine/google/appengine/ext/webapp/util.py", line 68, in check_login
handler_method(self, *args)
File "[$PATH]/dev/projets/xxx/main.py", line 89, in get
gdata.gauth.ae_save(token, access_token_key)
File "[$PATH]/dev/projets/xxx/gdata/gauth.py", line 1593, in ae_save
return gdata.alt.app_engine.set_token(key_name, token_to_blob(token))
File "[$PATH]/dev/projets/xxx/gdata/alt/app_engine.py", line 92, in set_token
if Token(key_name=unique_key, t=token_str).put():
File "[$PATH]/dev/outils/google_appengine/google/appengine/ext/db/__init__.py", line 973, in __init__
prop.__set__(self, value)
File "[$PATH]/dev/outils/google_appengine/google/appengine/ext/db/__init__.py", line 613, in __set__
value = self.validate(value)
File "[$PATH]/dev/outils/google_appengine/google/appengine/ext/db/__init__.py", line 2779, in validate
(self.name, self.data_type.__name__, err))
BadValueError: Property t must be convertible to a Blob instance (Blob() argument should be str instance, not unicode)
But gdata.gauth.access_token calls gdata.gauth.upgrade_to_access_token which return the token with some modification.
If i try with token_to_blob, i have this exception UnsupportedTokenType: Unable to serialize token of type <type 'unicode'>
** How save the new access Token ?**
main.py :
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app, login_required
from google.appengine.api import users
import gdata.gauth
import atom.http_core
SETTINGS = {
'APP_NAME': 'xxx',
'CLIENT_ID':'xxx.apps.googleusercontent.com',
'CLIENT_SECRET':'xxx',
'SCOPES': ['https://www.google.com/m8/feeds/', 'https://docs.google.com/feeds/', 'https://www.google.com/calendar/feeds/'],
'USER_AGENT' : 'xxxs',
'OAUTH2CALLBACK':'http://localhost:8080/oauth2callback'
#'OAUTH2CALLBACK':'http://example.com/oauth2callback'
}
class Home(webapp.RequestHandler):
def get(self):
"""Home"""
if users.get_current_user():
self.redirect("/step1")
else:
self.response.out.write("<a href='/step1'>Sign in google</a><br />")
class Fetcher(webapp.RequestHandler):
#login_required
def get(self):
"""This handler is responsible for fetching an initial OAuth
request token and redirecting the user to the approval page."""
current_user = users.get_current_user()
#create token
token = gdata.gauth.OAuth2Token(client_id = SETTINGS['CLIENT_ID'],
client_secret = SETTINGS['CLIENT_SECRET'],
scope = ' '.join(SETTINGS['SCOPES']),
user_agent = SETTINGS['USER_AGENT'])
url = token.generate_authorize_url(redirect_uri = SETTINGS['OAUTH2CALLBACK'])
#save token to datastore
gdata.gauth.ae_save(token, current_user.user_id())
message = """<a href="%s">
Request token for the Google Documents Scope</a>"""
self.response.out.write(message % url)
self.response.out.write(" ; redirect uri : %s" % token.redirect_uri)
class RequestTokenCallback(webapp.RequestHandler):
#login_required
def get(self):
"""When the user grants access, they are redirected back to this
handler where their authorized request token is exchanged for a
long-lived access token."""
current_user = users.get_current_user()
#get token from callback uri
url = atom.http_core.Uri.parse_uri(self.request.uri)
# get token from datastore
token = gdata.gauth.ae_load(current_user.user_id())
# SOLUTION 1
token.redirect_uri = SETTINGS['OAUTH2CALLBACK']
if isinstance(token, gdata.gauth.OAuth2Token):
if 'error' in url.query:
pass
else:
token.get_access_token(url.query)
gdata.gauth.ae_save(gdata.gauth.token_to_blob(token), "access_token_" + current_user.user_id())
def main():
application = webapp.WSGIApplication([('/', Home),
('/step1', Fetcher),
('/oauth2callback', RequestTokenCallback)],
debug = True)
run_wsgi_app(application)
if __name__ == '__main__':
main()
app.yaml :
application: xxx
version: 2
runtime: python
api_version: 1
handlers:
- url: .*
script: main.py
When you call AeLoad, you need to look at AeSave. You'll notice in the source code that token_to_blob is called.
However, in the source for token_to_blob, the redirect_uri is not saved to the blob, so you'll need to keep it around and call:
token = gdata.gauth.ae_load(current_user.user_id())
token.redirect_uri = SETTINGS['OAUTH2CALLBACK']
For reference, see another related post.
Answer to Question 2: Read the traceback: Blob() argument should be str instance, not unicode. Which version of Python are you using locally?