I'm having an error on a python file. What it does is to get acces to an specific google API. OAuth2.0. But that's not the wrong part. The wrong part takes part of argparse (Retriving arguments from console by adding --something="").
Here's my code:
import argparse
import os
import pprint
import sys
import time
import httplib2
from apiclient import discovery
from oauth2client import file
from oauth2client import tools
from oauth2client import client
# Time to wait (in seconds) between successive checks of training status.
SLEEP_TIME = 10
# Declare command-line flags.
argparser = argparse.ArgumentParser(add_help=False)
argparser.add_argument('object_name',
help='Full Google Storage path of csv data (ex bucket/object)')
argparser.add_argument('id',
help='Model Id of your choosing to name trained model')
#argparser.add_argument('action');
def print_header(line):
'''Format and print header block sized to length of line'''
header_str = '='
header_line = header_str * len(line)
print '\n' + header_line
print line
print header_line
def main(argv):
parent_parsers = [tools.argparser]
parent_parsers.extend(parents)
parser = argparse.ArgumentParser(
description=doc,
formatter_class=argparse.RawDescriptionHelpFormatter,
parents=parent_parsers)
flags = parser.parse_args(argv[1:])
scope='https://www.googleapis.com/auth/prediction'
client_secrets = os.path.join(os.path.dirname(__file__),
'client_secrets.json')
flow = client.flow_from_clientsecrets(client_secrets,
scope=scope,
message=tools.message_if_missing(client_secrets))
storage = file.Storage('prediction.dat')
credentials = storage.get()
if credentials is None or credentials.invalid:
credentials = tools.run_flow(flow, storage, flags)
http = credentials.authorize(http = httplib2.Http())
service = discovery.build('prediction', 'v1.6', http=http)
try:
papi = service.trainedmodels()
print_header('Fetching list of first ten models')
result = papi.list(maxResults=10).execute()
print 'List results:'
pprint.pprint(result)
except client.AccessTokenRefreshError:
print ("The credentials have been revoked or expired, please re-run"
"the application to re-authorize")
if __name__ == '__main__':
main(sys.argv)
On this line--> parent_parsers = [tools.argparser] I'm having that error:
line 75, in main
parent_parsers = [tools.argparser]
AttributeError: 'module' object has no attribute 'argparser'
The tools.py file is that one:
import BaseHTTPServer
import argparse
import httplib2
import logging
import os
import socket
import sys
import webbrowser
from oauth2client import client
from oauth2client import file
from oauth2client import util
try:
from urlparse import parse_qsl
except ImportError:
from cgi import parse_qsl
_CLIENT_SECRETS_MESSAGE = """WARNING: Please configure OAuth 2.0
To make this sample run you will need to populate the client_secrets.json file
found at:
%s
with information from the APIs Console <https://code.google.com/apis/console>.
"""
# run_parser is an ArgumentParser that contains command-line options expected
# by tools.run(). Pass it in as part of the 'parents' argument to your own
# ArgumentParser.
argparser = argparse.ArgumentParser(add_help=False)
argparser.add_argument('--auth_host_name', default='localhost',
help='Hostname when running a local web server.')
argparser.add_argument('--noauth_local_webserver', action='store_true',
default=False, help='Do not run a local web server.')
argparser.add_argument('--auth_host_port', default=[8080, 8090], type=int,
nargs='*', help='Port web server should listen on.')
argparser.add_argument('--logging_level', default='ERROR',
choices=['DEBUG', 'INFO', 'WARNING', 'ERROR',
'CRITICAL'],
help='Set the logging level of detail.')
class ClientRedirectServer(BaseHTTPServer.HTTPServer):
"""A server to handle OAuth 2.0 redirects back to localhost.
Waits for a single request and parses the query parameters
into query_params and then stops serving.
"""
query_params = {}
class ClientRedirectHandler(BaseHTTPServer.BaseHTTPRequestHandler):
"""A handler for OAuth 2.0 redirects back to localhost.
Waits for a single request and parses the query parameters
into the servers query_params and then stops serving.
"""
def do_GET(s):
"""Handle a GET request.
Parses the query parameters and prints a message
if the flow has completed. Note that we can't detect
if an error occurred.
"""
s.send_response(200)
s.send_header("Content-type", "text/html")
s.end_headers()
query = s.path.split('?', 1)[-1]
query = dict(parse_qsl(query))
s.server.query_params = query
s.wfile.write("<html><head><title>Authentication Status</title></head>")
s.wfile.write("<body><p>The authentication flow has completed.</p>")
s.wfile.write("</body></html>")
def log_message(self, format, *args):
"""Do not log messages to stdout while running as command line program."""
pass
#util.positional(3)
def run_flow(flow, storage, flags, http=None):
logging.getLogger().setLevel(getattr(logging, flags.logging_level))
if not flags.noauth_local_webserver:
success = False
port_number = 0
for port in flags.auth_host_port:
port_number = port
try:
httpd = ClientRedirectServer((flags.auth_host_name, port),
ClientRedirectHandler)
except socket.error, e:
pass
else:
success = True
break
flags.noauth_local_webserver = not success
if not success:
print 'Failed to start a local webserver listening on either port 8080'
print 'or port 9090. Please check your firewall settings and locally'
print 'running programs that may be blocking or using those ports.'
print
print 'Falling back to --noauth_local_webserver and continuing with',
print 'authorization.'
print
if not flags.noauth_local_webserver:
oauth_callback = 'http://%s:%s/' % (flags.auth_host_name, port_number)
else:
oauth_callback = client.OOB_CALLBACK_URN
flow.redirect_uri = oauth_callback
authorize_url = flow.step1_get_authorize_url()
if not flags.noauth_local_webserver:
webbrowser.open(authorize_url, new=1, autoraise=True)
print 'Your browser has been opened to visit:'
print
print ' ' + authorize_url
print
print 'If your browser is on a different machine then exit and re-run this'
print 'application with the command-line parameter '
print
print ' --noauth_local_webserver'
print
else:
print 'Go to the following link in your browser:'
print
print ' ' + authorize_url
print
code = None
if not flags.noauth_local_webserver:
httpd.handle_request()
if 'error' in httpd.query_params:
sys.exit('Authentication request was rejected.')
if 'code' in httpd.query_params:
code = httpd.query_params['code']
else:
print 'Failed to find "code" in the query parameters of the redirect.'
sys.exit('Try running with --noauth_local_webserver.')
else:
code = raw_input('Enter verification code: ').strip()
try:
credential = flow.step2_exchange(code, http=http)
except client.FlowExchangeError, e:
sys.exit('Authentication has failed: %s' % e)
storage.put(credential)
credential.set_store(storage)
print 'Authentication successful.'
return credential
def message_if_missing(filename):
"""Helpful message to display if the CLIENT_SECRETS file is missing."""
return _CLIENT_SECRETS_MESSAGE % filename
try:
from old_run import run
except ImportError:
def run(*args, **kwargs):
raise NotImplementedError(
'The gflags library must be installed to use tools.run(). '
'Please install gflags or preferrably switch to using '
'tools.run_flow().')
I don't understand the meaning of the error, it may be an import issue but I don't know.
Thanks!
You need to make sure the oauth tools are setup properly:
python setup_oauth2client.py install
it's in the base directory
Related
I am setting up a flask server that will act as a webhook to the twitter account activity api. However I came up with this issue that I have no idea how to solve, I'm fairly new to programming so please bear with me. I just used this repository https://github.com/RickRedSix/twitter-webhook-boilerplate-python/blob/master/Main.py
This is the error:
line 28, in twitterCrcValidation
key=bytes(CONSUMER_SECRET, encoding ='utf-8'),
TypeError: encoding without a string argument
Here's the code:
#!/usr/bin/env python
from flask import Flask, request, send_from_directory, make_response
from http import HTTPStatus
import Twitter, hashlib, hmac, base64, os, logging, json
from dotenv import load_dotenv
load_dotenv('.env')
CONSUMER_SECRET = os.getenv('CONSUMER_SECRET')
CURRENT_USER_ID = os.getenv('CURRENT_USER_ID')
app = Flask(__name__)
#generic index route
#app.route('/')
def default_route():
return send_from_directory('www', 'index.html')
#The GET method for webhook should be used for the CRC check
#TODO: add header validation (compare_digest https://docs.python.org/3.6/library/hmac.html)
#app.route("/webhook", methods=["GET"])
def twitterCrcValidation():
crc = request.args['crc_token']
validation = hmac.new(
key=bytes(CONSUMER_SECRET, encoding ='utf-8'),
msg=bytes(crc, encoding = 'utf-8'),
digestmod = hashlib.sha256
)
digested = base64.b64encode(validation.digest())
response = {
'response_token': 'sha256=' + format(str(digested)[2:-1])
}
print('responding to CRC call')
return json.dumps(response)
#The POST method for webhook should be used for all other API events
#TODO: add event-specific behaviours beyond Direct Message and Like
#app.route("/webhook", methods=["POST"])
def twitterEventReceived():
requestJson = request.get_json()
#dump to console for debugging purposes
print(json.dumps(requestJson, indent=4, sort_keys=True))
if 'favorite_events' in requestJson.keys():
#Tweet Favourite Event, process that
likeObject = requestJson['favorite_events'][0]
userId = likeObject.get('user', {}).get('id')
#event is from myself so ignore (Favourite event fires when you send a DM too)
if userId == CURRENT_USER_ID:
return ('', HTTPStatus.OK)
Twitter.processLikeEvent(likeObject)
elif 'direct_message_events' in requestJson.keys():
#DM recieved, process that
eventType = requestJson['direct_message_events'][0].get("type")
messageObject = requestJson['direct_message_events'][0].get('message_create', {})
messageSenderId = messageObject.get('sender_id')
#event type isnt new message so ignore
if eventType != 'message_create':
return ('', HTTPStatus.OK)
#message is from myself so ignore (Message create fires when you send a DM too)
if messageSenderId == CURRENT_USER_ID:
return ('', HTTPStatus.OK)
Twitter.processDirectMessageEvent(messageObject)
else:
#Event type not supported
return ('', HTTPStatus.OK)
return ('', HTTPStatus.OK)
if __name__ == '__main__':
# Bind to PORT if defined, otherwise default to 65010.
port = int(os.environ.get('PORT', 65010))
gunicorn_logger = logging.getLogger('gunicorn.error')
app.logger.handlers = gunicorn_logger.handlers
app.logger.setLevel(gunicorn_logger.level)
app.run(host='0.0.0.0', port=port, debug=True)
You need to verify input to your program and environment variables are no exception. As a minumum, check that these variables actually exist. os.getenv returns None if the environment variable doesn't exist. None is not a string and thus your error. You could do this with a slightly different os call.
CONSUMER_SECRET = os.environ['CONSUMER_SECRET']
CURRENT_USER_ID = os.environ['CURRENT_USER_ID']
Now an exception is raised on failure. This could be wrapped in an exception handler if you want different error reporting than the standard traceback.
I have a working python/tk program that runs a cgi script based on user selection. I'm working to cut this down to a small script that just focuses on one particular cgi script. It appears to be getting the session id correctly but when I launch the browser I keep getting "access denied". As the other program works I not expecting any issues from the website. Any help will be appreciated.
UPDATE:
If I use a debugger and set a breakpoint on the line print url the url printed in the console, as seen below, does work. I now know the session id token is good.
Also if I step into the webbrowser function and then step over after that the script also works.
Here is my code.
import json
import tornado.web
import tornado.websocket
from tornado import gen
import tornado.ioloop
import webbrowser
from struct import *
request_id = 71
ip_address = "10.22.4.14"
# ************************************************
# Procedure to open websocket and get session id
# ***********************************************
#gen.coroutine
def open_ws(ip, username, password):
global client
global request_id
global session_id
ws_url = "ws://" + ip + ":7011/"
try:
client = yield tornado.websocket.websocket_connect(ws_url, None, None, 5, None, None)
# print("websocket %s open" % ws_url)
except error:
exit()
# Send Mercury login request
JSON = '{"requests":[{"request_id": %s, "login":{"username": "%s","password": "%s"}}]}' % (str(request_id), username, password)
client.write_message(JSON)
results = yield client.read_message()
# print("msg is %s" % results)
# Parse the response of login request to get the error code
parsed_json = json.loads(results)
err_code = parsed_json['responses'][0]['request_response']['result']['err_code']
if 0 == err_code:
# Parse the response of get_command_result to get the session id
session_id = parsed_json['responses'][0]['request_response']['login']['session_id']
# print("login succeeded - session id: %s" % session_id)
else:
print("login failed")
# error_exit(err_code)
def get_token():
tornado.ioloop.IOLoop.instance().run_sync(lambda: open_ws(ip_address, 'admin', 'admin'))
return session_id
session_id = get_token()
print "Token is " + session_id
url = "http://" + ip_address + "/scripts/dostuff.cgi?session=" + session_id
print url # add breakpoint here
# launch browser
webbrowser.open(url)
Console output:
Token is 7zNSZX9liaUDFFN0ijn-LWQ8
http://10.222.4.14/scripts/dostuff.cgi?session=7zNSZX9liaUDFFN0ijn-LWQ8
Resolved. The script was ending therefore closing the socket before the browser had a chance to respond to the request
im trying to use the tornado aysnchttpclient to upload some data and its not working:
the error i get is HTTP 404: Not Found ,
here is some code im using:
import os
import tornado.web
from tornado.ioloop import IOLoop
from tornado.httpclient import AsyncHTTPClient, HTTPRequest
def send_files():
datfile = None
with open('test_data/1.dat','rb') as datf:
datfile = datf.read()
ur = 'http://swiftauth:8080/v1/AUTH_test'+'/'+'cont'+'/'+'loldat'
print ('sending to %s'% ur )
pot = HTTPRequest( ur , method='PUT',
headers={'X-Auth-Token':'AUTH_tkbfa9045f97c040fbbd10f0bd0970d78d',
'Content-Type': 'text/plain'},
body =datfile,allow_nonstandard_methods=True )
http_put_client.fetch(pot, handle_put_rep)
def handle_put_rep(response):
if response.error:
print ('this is ', response.error, 'type of error')
else:
print ('success in put',response.headers)
http_put_client = AsyncHTTPClient()
send_files()
loop = IOLoop.instance()
if __name__ == "__main__":
loop.start()
everything seems fine, i can use the asyncclient to GET auth tokens, but not upload
and the commandline swift client is working, all using the same credentials.
('AUTH_tkbfa9045f97c040fbbd10f0bd0970d78d', 'AUTH_TOKEN')
('http://swiftauth:8080/v1/AUTH_test', 'URL')
('swiftauth:8080', 'CONNECTION_ENDPOINT')
('/v1/AUTH_test/Tor', 'CONTAINER_PATH')
I am trying to post to the wall of a facebook page that I am administrator (not profile), however no luck. How do I achieve this ? I'm stucked at the page access token retrieval part.
#!/usr/bin/python
# coding: utf-8
import facebook
import urllib
import urlparse
import subprocess
import warnings
# Hide deprecation warnings. The facebook module isn't that up-to-date (facebook.GraphAPIError).
warnings.filterwarnings('ignore', category=DeprecationWarning)
# Parameters of your app and the id of the profile you want to mess with.
FACEBOOK_APP_ID = 'XXXXXXXXXXXXXX'
FACEBOOK_APP_SECRET = 'XXXXXXXXXXXXXXXXXXXXX'
FACEBOOK_PROFILE_ID = 'XXXXXXXXXXX'
# Trying to get an access token. Very awkward.
oauth_args = dict(client_id = FACEBOOK_APP_ID,
client_secret = FACEBOOK_APP_SECRET,
scope = 'manage_pages',
response_type = 'token'
)
oauth_curl_cmd = ['curl',
'https://graph.facebook.com/oauth/access_token?' + urllib.urlencode(oauth_args)]
oauth_response = subprocess.Popen(oauth_curl_cmd,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE).communicate()[0]
print urllib.urlencode(oauth_args)
try:
oauth_access_token = urlparse.parse_qs(str(oauth_response))['access_token'][0]
except KeyError:
print('Unable to grab an access token!')
exit()
print oauth_access_token
facebook_graph = facebook.GraphAPI(oauth_access_token)
# Try to post something on the wall.
try:
fb_response = facebook_graph.put_wall_post('Hello from Python', \
profile_id = FACEBOOK_PROFILE_ID)
print fb_response
except facebook.GraphAPIError as e:
print 'Something went wrong:', e.type, e.message
I would not recommend doing this through the command line with curl as it is less secure and less reliable. You can do all of this with the urllib2 and json modules
to get the access token you just want to make a call to https://graph.facebook.com/oauth/access_token?client_id=YOUR_APP_ID&client_secret=YOUR_APP_SECRET&grant_type=client_credentials
so you would do:
url='https://graph.facebook.com/oauth/access_token?client_id=YOUR_APP_ID&client_secret=YOUR_APP_SECRET&grant_type=client_credentials'
target=urllib2.urlopen(url)
token = target.read()[13:]
EDIT:
My bad, I forgot that facebook/oauth gives you the access token in plain text so you don't need the json module. I've updated the example to show what you should be doing. Note target.read() will give you the string 'access_token=ACCESS_TOKEN' and then you are just parsing it to remove the identifier.
to see what response is go to the url and put in your information you will a json dict with acess_token.
the second half of this page should have all the information you need.
I'm using an open source web service python application to send email through GAE but if the name or email body contains Arabic or Hebrew characters the application throws some errors (e.g "The indicated parameters are not valid"). Therefore I need to know how to fix this issue. I have to note that I'm a Python beginner (one week since I started playing with Python).
#
import cgi
import os
import logging
import contextlib
from xml.dom import minidom
from xml.dom.minidom import Document
import exceptions
import warnings
import imghdr
from google.appengine.api import images
from google.appengine.api import users
from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext.webapp import template
from google.appengine.api import mail
import wsgiref.handlers
# START Constants
CONTENT_TYPE_HEADER = "Content-Type"
CONTENT_TYPE_TEXT = "text/plain"
XML_CONTENT_TYPE = "application/xml"
XML_ENCODING = "utf-8"
"""
Allows you to specify IP addresses and associated "api_key"s to prevent others from using your app.
Storage and Manipulation methods will check for this "api_key" in the POST/GET params.
Retrieval methods don't use it (however you could enable them to use it, but maybe rewrite so you have a "read" key and a "write" key to prevent others from manipulating your data).
Set "AUTH = False" to disable (allowing anyone use your app and CRUD your data).
To generate a hash/api_key visit https://www.grc.com/passwords.htm
To find your ip visit http://www.whatsmyip.org/
"""
AUTH = False
# END Constants
# START Exception Handling
class Error(StandardError):
pass
class Forbidden(Error):
pass
logging.getLogger().setLevel(logging.DEBUG)
#contextlib.contextmanager
def mailExcpHandler(ctx):
try:
yield {}
except (ValueError), exc:
xml_error_response(ctx, 400 ,'app.invalid_parameters', 'The indicated parameters are not valid: ' + exc.message)
except (Forbidden), exc:
xml_error_response(ctx, 403 ,'app.forbidden', 'You don\'t have permission to perform this action: ' + exc.message)
except (Exception), exc:
xml_error_response(ctx, 500 ,'system.other', 'An unexpected error in the web service has happened: ' + exc.message)
def xml_error_response(ctx, status, error_id, error_msg):
ctx.error(status)
doc = Document()
errorcard = doc.createElement("error")
errorcard.setAttribute("id", error_id)
doc.appendChild(errorcard)
ptext = doc.createTextNode(error_msg)
errorcard.appendChild(ptext)
ctx.response.headers[CONTENT_TYPE_HEADER] = XML_CONTENT_TYPE
ctx.response.out.write(doc.toxml(XML_ENCODING))
# END Exception Handling
# START Helper Methods
def isAuth(ip = None, key = None):
if AUTH == False:
return True
elif AUTH.has_key(ip) and key == AUTH[ip]:
return True
else:
return False
# END Helper Methods
# START Request Handlers
class Send(webapp.RequestHandler):
def post(self):
"""
Sends an email based on POST params. It will queue if resources are unavailable at the time.
Returns "Success"
POST Args:
to: the receipent address
from: the sender address (must be a registered GAE email)
subject: email subject
body: email body content
"""
with mailExcpHandler(self):
# check authorised
if isAuth(self.request.remote_addr,self.request.POST.get('api_key')) == False:
raise Forbidden("Invalid Credentials")
# read data from request
mail_to = str(self.request.POST.get('to'))
mail_from = str(self.request.POST.get('from'))
mail_subject = str(self.request.POST.get('subject'))
mail_plain = str(self.request.POST.get('plain'))
mail_html = str(self.request.POST.get('html'))
message = mail.EmailMessage()
message.sender = mail_from
message.to = mail_to
message.subject = mail_subject
message.body = mail_plain
if mail_html != None and mail_html != "":
message.html = mail_html
message.send()
self.response.headers[CONTENT_TYPE_HEADER] = CONTENT_TYPE_TEXT
self.response.out.write("Success")
# END Request Handlers
# START Application
application = webapp.WSGIApplication([
('/send', Send)
],debug=True)
def main():
run_wsgi_app(application)
if __name__ == '__main__':
main()
# END Application
mail_to = str(self.request.POST.get('to'))
mail_from = str(self.request.POST.get('from'))
mail_subject = str(self.request.POST.get('subject'))
mail_plain = str(self.request.POST.get('plain'))
mail_html = str(self.request.POST.get('html'))
I doubt you need to convert them to strings. Try without str(), it could work.