Google Cloud Pub Sub With Service Account - python

Hi everyone I am having an issue with pub sub that is driving me nuts. Basically I have a service account with admin priivs for pubsub but I can't get any thing to work and am getting the following error:
ERROR:root:AuthMetadataPluginCallback "" raised exception!
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/grpc/_plugin_wrapping.py", line 77, in call
callback_state, callback))
File "/usr/local/lib/python2.7/dist-packages/google/auth/transport/grpc.py", line 77, in call
callback(self._get_authorization_headers(context), None)
File "/usr/local/lib/python2.7/dist-packages/google/auth/transport/grpc.py", line 61, in _get_authorization_headers
self._credentials.before_request(
AttributeError: 'str' object has no attribute 'before_request'
Code is super simple
from google.cloud import pubsub
credentials = '/home/airflow/Desktop/test/config/test.json'
publisher = pubsub.PublisherClient(credentials=credentials)
topic_path = publisher.topic_path("test-proj", "test")
for n in range(1, 2):
data = u'Message number {}'.format(n)
# Data must be a bytestring
data = data.encode('utf-8')
test = publisher.publish(topic_path, data=data).result()
print(test, "s")
Amy help would be really appreciated as the error message doesn't make much sense to me. Thanks

The credentials argument for PublisherClient is not a string. It is a google.auth.credentials.Credentials object. The google-auth-guide indicates how to create it:
from google.oauth2 import service_account
credentials = service_account.Credentials.from_service_account_file(
'/home/airflow/Desktop/test/config/test.json')

Related

Pythonanywhere: Twitter API authenticates from bash, but fails on scheduled task

I'm using the python-twitter (not tweepy) module in my application.
I have a script set up (maketweet.py) that, when I run it from bash / console, works successfully (i.e. it makes a tweet).
The problem I'm having is that when I run the same script as a scheduled task, I get an error:
Traceback (most recent call last):
File "/home/dir1/dir2/proj/maketweet.py", line 21, in <module>
api = create_api()
File "/home/dir1/dir2/proj/config.py", line 31, in create_api
if api.VerifyCredentials():
File "/home/dir1/.local/lib/python3.8/site-packages/twitter/api.py", line 4699, in VerifyCredentials
resp = self._RequestUrl(url, 'GET', data)
File "/home/dir1/.local/lib/python3.8/site-packages/twitter/api.py", line 4959, in _RequestUrl
raise TwitterError("The twitter.Api instance must be authenticated.")
twitter.error.TwitterError: The twitter.Api instance must be authenticated.
The other problem I'm having is that I can't conceive why it would make a difference that I'm using a scheduled task, rather than running the file directly from bash. Here are the contents of config.py:
#!/usr/bin/python3.8
import twitter
import os
import logging
from dotenv import load_dotenv
logger = logging.getLogger()
# project folder is one level up from file location
project_folder = pathlib.Path(__file__).parent.absolute()
load_dotenv(os.path.join(project_folder, '.env'))
# Authenticate to Twitter and create API object
TWITTER_CONSUMER_API_KEY = os.getenv("TWITTER_CONSUMER_API_KEY")
TWITTER_CONSUMER_API_SECRET = os.getenv("TWITTER_CONSUMER_API_SECRET")
TWITTER_ACCESS_TOKEN = os.getenv("TWITTER_ACCESS_TOKEN")
TWITTER_ACCESS_SECRET = os.getenv("TWITTER_ACCESS_SECRET")
def create_api():
# Create API object
api = twitter.Api(
access_token_key = TWITTER_ACCESS_TOKEN,
access_token_secret = TWITTER_ACCESS_SECRET,
consumer_key = TWITTER_CONSUMER_API_KEY,
consumer_secret = TWITTER_CONSUMER_API_SECRET,
sleep_on_rate_limit=True)
# test API object
if api.VerifyCredentials():
pass
else:
logger.error("Error creating API", exc_info=True)
raise Exception("Twitter user authentication error")
logger.info("API created")
return api
Obviously there's an error in creating the API. I imagine this has something to do with the environment variables and how they are accessed through scheduled tasks vs. bash. Just really not sure how to figure this one out...

How do I get ondapyV20 to complete authorization?

Here is my code:
from oandapyV20 import API
import oandapyV20.endpoints.trades as trades
api = API(access_token="xxx")
accountID = "xxx-xxx-xxxxxxx-xxx"
r = trades.TradesList(accountID)
print("REQUEST:{}".format(r))
rv = api.request(r)
print("RESPONSE:\n{}".format(json.dumps(rv, indent=2)))
I get the following error:
Traceback (most recent call last):
File "C:\Users\Administrator\Desktop\oanda tester.py", line 10, in
rv = api.request(r)
File "C:\Python37\lib\site-packages\oandapyV20\oandapyV20.py", line 306, in request
request_args, headers=headers)
File "C:\Python37\lib\site-packages\oandapyV20\oandapyV20.py", line 243, in __request
response.content.decode('utf-8'))
oandapyV20.exceptions.V20Error: {"errorMessage":"Insufficient authorization to perform request."}
My token and account info is correct.
This code was copied straight from documentation.
Am I missing something here?
Try this instead:
from oandapyV20 import API
import oandapyV20.endpoints.trades as trades
import json
access_token="xxx"
accountID = "xxxx"
client= API(access_token=access_token,environment="live" or "practice")
r = trades.TradesList(accountID)
print("REQUEST:{}".format(r))
rv = client.request(r)
print("RESPONSE:\n{}".format(json.dumps(rv, indent=2)))
When you define the client object, you should specify if your account is of type live or practice:
client= API(access_token = access_token, environment = "live")
Regularly, when you work with practice accounts you define the client object like this:
client= API(access_token = access_token)

Multiple scopes results in failed authorization

I've been trying to get my authorization working using the Authorization Code Flow with the example from Spotipy API, as seen below.
import sys
import spotipy
import spotipy.util as util
scope = 'user-library-read playlist-read-private' # or else
if len(sys.argv) > 1:
username = sys.argv[1]
else:
print("Usage: %s username" % (sys.argv[0],))
sys.exit()
token = util.prompt_for_user_token(username, scope)
if token:
sp = spotipy.Spotify(auth=token)
results = sp.current_user_saved_tracks()
for item in results['items']:
track = item['track']
print(track['name'] + ' - ' + track['artists'][0]['name'])
else:
print("Can't get token for", username)
I managed to get it working just fine with the scope being 'user-library-read', but upon changing the scope or adding another, I get the request to re-authenticate. I copy the redirect URL in the editor as usual and get the following error:
Traceback (most recent call last):
File "C:/Users/Joel/PycharmProjects/untitled1/test.py", line 13, in <module>
token = util.prompt_for_user_token(username, scope)
File "C:\Users\Joel\.virtualenvs\untitled1-1cFj5f_i\lib\site-packages\spotipy\util.py", line 86, in prompt_for_user_token
token_info = sp_oauth.get_access_token(code)
File "C:\Users\Joel\.virtualenvs\untitled1-1cFj5f_i\lib\site-packages\spotipy\oauth2.py", line 217, in get_access_token
raise SpotifyOauthError(response.reason)
spotipy.oauth2.SpotifyOauthError: Bad Request
Any ideas what I'm doing wrong here? I'm stumped, since it works just fine with that one specific scope (and doesn't require me to authorize since I've already done it), but with others I get this.
Also, when running the code in my terminal, it requires me to authorize as well, only I get the following error in the browser: INVALID_CLIENT: Invalid redirect URI

Foursquare authentication - 'No handlers could be found for logger "foursquare"'

I'm starting with the Foursquare API, in Python, and I'm not sure why I can't authenticate.
Following the tutorial, so far I have this piece of code:
import foursquare
client = foursquare.Foursquare(client_id=myid, client_secret=mysecret,
redirect_uri='http://fondu.com/oauth/authorize')
auth_uri = client.oauth.auth_url()
access_token = client.oauth.get_token('XX_CODE_RETURNED_IN_REDIRECT_XX')
client.set_access_token(access_token)
client.venues.explore(params={'near': 'New York, NY', 'time' : date})
I've created an app here:
https://foursquare.com/developers/apps
and I'm using both:
Client id
Client secret
shown in the page.
However, when running this code, I get:
No handlers could be found for logger "foursquare"
Traceback (most recent call last):
File "noiseInference.py", line 270, in <module>
getFoursquareCheckIns(date)
File "noiseInference.py", line 156, in getFoursquareCheckIns
access_token = client.oauth.get_token('XX_CODE_RETURNED_IN_REDIRECT_XX')
File "/Library/Python/2.7/site-packages/foursquare/__init__.py", line 134, in get_token
response = _request_with_retry(url)
File "/Library/Python/2.7/site-packages/foursquare/__init__.py", line 707, in _request_with_retry
return _process_request_with_httplib2(url, headers, data)
File "/Library/Python/2.7/site-packages/foursquare/__init__.py", line 730, in _process_request_with_httplib2
return _check_response(data)
File "/Library/Python/2.7/site-packages/foursquare/__init__.py", line 763, in _check_response
raise FoursquareException(errmsg)
foursquare.FoursquareException: Response format invalid, missing meta property. data: {u'error': u'invalid_client'}
Not sure what's the problem.
The handler message is just complaining you didn't set up a logger under for the foursquare namespace.
Your real error is the message at the end of the stack trace:
foursquare.FoursquareException:
Response format invalid, missing meta property. data: {u'error': u'invalid_client'}
The message indicates that your client's credentials are incorrect. The credentials aren't fully checked until you attempt to use the client for a privileged action like client.set_access_token, so the most likely culprit here is to look at what you pass for client_secret when constructing the Foursquare client object.
client_id is probably not the problem because you'd have to go through the URL-OAuth flow in order to get the access_token you use.

boto SQS NoSuchVersion Error

My problem is best described by the following script:
import boto
boto.__version__
# OUT: '2.19.0'
from boto.ec2.connection import EC2Connection
ec2 = EC2Connection(**creds)
regions = ec2.get_all_regions()
from boto.sqs.connection import SQSConnection
regions[0]
# OUT: RegionInfo:eu-west-1
sqs = SQSConnection(region=regions[0], **creds)
sqs.get_all_queues()
# OUT: Traceback (most recent call last):
# OUT: File "<input>", line 1, in <module>
# OUT: File "/opt/zenoss/lib/python2.7/site-packages/boto/sqs/connection.py", line 338, in get_all_queues
# OUT: return self.get_list('ListQueues', params, [('QueueUrl', Queue)])
# OUT: File "/opt/zenoss/lib/python2.7/site-packages/boto/connection.py", line 1119, in get_list
# OUT: raise self.ResponseError(response.status, response.reason, body)
# OUT: SQSError: SQSError: 400 Bad Request
# OUT: <?xml version="1.0" encoding="UTF-8"?>
# OUT: <Response><Errors><Error><Code>NoSuchVersion</Code><Message>The requested version (2012-11-05) of service AmazonEC2 does not exist</Message></Error></Errors><RequestID>1600907e-6780-46f5-b5e6-e647a660abf8</RequestID></Response>
I could not find documentation for AWS or boto about meaning of this error, and how to fix it. Is that a bug of boto?
The problem with the above code is that the get_all_regions() call from the EC2 module returns a list of RegionInfo objects consisting of a region name and a region endpoint. But the endpoint is for the EC2 service, not SQS. So, if you pass that RegionInfo into the SQSConnection constructor it will end up trying to make SQS requests against an EC2 endpoint which results in the NoSuchVersion error.
Here's how I would do this:
import boto.sqs
sqs = boto.sqs.connect_to_region('eu-west-1')
sqs.get_all_queues()
Similarly, if you need an EC2 connection:
import boto.ec2
ec2 = boto.ec2.connect_to_region('eu-west-1')

Categories

Resources