I have created a wheel file and I m trying to invoke the method in synapse but am unable to do so.On trying to call the method _buildJSONdata() using below
import cloudapi
from cloudapi import cloudalert
api=cloudalert.CloudLink()
Data = {"Name": "ABC","email":"df#example.com","subject":"Alert"}
api._buildJSONdata(Data)
I am getting the error AttributeError: 'CloudLink' object has no attribute 'Data'.I have already defined the argument inside the definition and already using the data variable while invoking the said method
Contents of __init__.py
from .cloudalert import CloudLink
Contents of setup.py
import setuptools
with open("README.md", "r") as fh:
long_description = fh.read()
setuptools.setup(
name="CloudAPI",
version="0.0.1",
author="XYZ",
author_email="abc#example.com",
description="Package expose Cloud as library",
long_description=long_description,
long_description_content_type="text/markdown",
packages=setuptools.find_packages(),
install_requires=["adal"],
classifiers=["Programming Language :: Python :: 3",],
python_requires='>=3.7',
)
Folder structure
Below is cloudalert.py content
import json
import datetime
import hashlib
import json
import sys
import traceback
import adal
import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry
import logging
from functools import wraps
import sys
def create_logger():
#create a logger object
#logger = logging.getLogger()
logger = logging.getLogger()
logger.setLevel(logging.INFO)
logfile = logging.FileHandler('exc_logger.log')
#logfile = logging.StreamHandler(sys.stdout)
fmt = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
formatter = logging.Formatter(fmt)
logfile.setFormatter(formatter)
logger.addHandler(logfile)
return logger
logger = create_logger()
def exception(logger):
def decorator(func):
#wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except:
issue = "exception in "+func.__name__+"\n"
issue = issue+"-------------------------\
------------------------------------------------\n"
logger.exception(issue)
raise
return wrapper
return decorator
class CloudLink(object):
_token = None
_instance = None
http = None
#staticmethod
def getInstance():
if not CloudLink._instance:
CloudLink._instance = CloudLink()
return CloudLink._instance
def __init__(self):
retry_strategy = Retry(
total=3,
backoff_factor=0,
status_forcelist=[429, 500, 502, 503, 504],
allowed_methods=["HEAD", "GET", "OPTIONS"],
)
adapter = HTTPAdapter(max_retries=retry_strategy)
self.http = requests.Session()
self.http.mount("https://", adapter)
self.http.mount("http://", adapter)
print("Inside init")
def parseJSON(self, t):
try:
eData = json.loads(t)
logger.info(f"Sending {eData} to Cloud")
self.sendToCloud(eData)
except ValueError as e:
print("Error: %s Please validate JSON in https://www.jsonschemavalidator.net/"% e)
return None # or: raise
def sendToCloud(self, eData):
#from notebookutils import mssparkutils
cloudtest = 'https://www.example.com/api/v1/event/fg'
cloudData = {"eData": eData, "metadata": self._buildMetadata()}
logger.info(f"Raising alert with data=({cloudData}")
response = self.http.post(
self.cloudtest, headers=self._buildHeaders(), json=cloudData
)
logger.info(f"cloud alert response={response}")
if response.status_code == 202 or response.status_code == 200:
logger.info("Mail sent to Cloud")
else:
raise Exception(f"Cloud reporting failed with Error {response}")
def _buildJSONdata(self,Data):
if len(self.Data) == 0:
raise Exception("JSON is empty")
else:
t = json.dumps(self.Data)
self.parseJSON(t)
def _buildMetadata(self):
return {
"messageType": "Send Email",
"messageVersion": "0.0.1",
"sender": "Send Email",
}
def _buildHeaders(self):
self._refreshADToken()
headers = {
"Authorization": "Bearer {}".format(self._token["accessToken"]),
"Content-type": "application/json",
"Accept": "text/plain",
}
return headers
def _refreshADToken(self):
def shouldRenew(token):
"""Returns True if the token should be renewed"""
expiresOn = datetime.datetime.strptime(
token["expiresOn"], "%Y-%m-%d %H:%M:%S.%f"
)
now = datetime.datetime.now()
return (expiresOn - now) < datetime.timedelta(minutes=5)
if not self._token or shouldRenew(self._token):
logger.info("Renewing credentials for Alerting")
result = None
try:
#from notebookutils import mssparkutils
cloudclient = "xxxxxxx"
clientid = "yyyyyyyyy"
clientcredentials = "ccccccccc"
authority_url = "https://login.microsoftonline.com/dddddddddd/"
context = adal.AuthenticationContext(authority_url)
result = context.acquire_token_with_client_credentials(cloudclient, clientid,clientcredentials)
except Exception as e:
error = "Failed to renew client credentials."
logger.info(error)
raise
if result and "accessToken" in result:
self._token = result
else:
logger.error(
"Failed to acquire bearer token. accessToken not found in result object on renewing credentials."
)
raise Exception("Could not acquire a bearer token")
Let me know in case if I m doing something wrong while invoking the function.
Related
I created this method after running into issues with my token timing out. The call worked when it was just a function and not part of a class. Here is the api class I created to call the msgraph. It successfully gets the token and stores it. I am just trying to call the method of get_users. The error is
<bound method msGraph.Decorators.refreshToken.<locals>.wrapper of <msgraph.msGraph object at 0x0197F628>>
class msGraph():
token = None
token_expiration = None
tenantid = None
user = None
apiurl = None
def __init__(self, tenantid):
self.tenantid = tenantid
try:
self.token = self.gettoken()
if self.token is None:
raise Exception("Request for access token failed.")
except Exception as e:
print(e)
else:
self.token_expiration = time.time() + 1800
def gettoken(self):
try:
apiurl = "https://login.microsoftonline.com/{}/oauth2/v2.0/token".format(self.tenantid)
headers = {'content-type': 'application/x-www-form-urlencoded'}
data = {'grant_type': 'client_credentials',
'client_id': 'xxx',
'client_secret': "xxx",
'scope': 'https://graph.microsoft.com/.default'}
newdata = urllib.parse.urlencode(data)
token = requests.post(apiurl, data=newdata, headers=headers).json()
except Exception as e:
print(e)
return None
else:
return token['access_token']
class Decorators():
#staticmethod
def refreshToken(decorated):
def wrapper(api, *args, **kwargs):
if time.time() > api.token_expiration:
api.gettoken
return decorated(api, *args, **kwargs)
return wrapper
#Decorators.refreshToken
def get_users(self):
try:
print('trying to get users')
apiurl = "https://graph.microsoft.com/v1.0/users"
authheader = "Bearer {}".format(self.token)
print(authheader)
header = {'Authorization': authheader, 'content-type': 'application/json'}
response = requests.get(apiurl, headers=header).json()
except Exception as e:
print(e)
return None
else:
users = response['value']
userList = []
for user in users:
if "#EXT" not in user['userPrincipalName']:
userList.append(user['userPrincipalName'])
return userList
This is how I am accessing it from the main script
main.py
from msgraph import msGraph
from processemails import userscan
tenant_id = "xxx"
company_Domain = "xxx"
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
api = msGraph(tenant_id)
userList = api.get_users()
for user in userList:
userscan(user, company_Domain, api)
quit()
I think you meant to write
userList = api.get_users()
with the parenthesis. Without the parenthesis, what you're assigning to userList is the function object, instead of the result of calling the function. And a function object is not an iterable, hence your error message.
I was working on mocking in Python. I want to mock a method from the class with a mocked object. Here is an example:
MyApp.py
import requests
class Client:
"""
Client to use in integration to fetch data from Chronicle Backstory
requires service_account_credentials : a json formatted string act as a token access
"""
def __init__(self, api_key, url, verify, proxies):
self.url = url
self.api_key = api_key
self.verify = verify
self.proxies = proxies
# a separate SDK that has initialized the request object
self.my_requests = requests
def http_request(self, method, url_suffix, params=None):
base_url = self.url + "/api/v4"
full_url = base_url + url_suffix
headers = {
'Authorization': self.api_key
}
validate_response(self.my_requests.request(
method,
full_url,
verify=self.verify,
proxies=self.proxies,
params=params,
headers=headers))
def validate_response(response):
status_code = response.status_code
resp_json = response.json()
if status_code != 200:
raise ValueError("Invalid argument value " + resp_json.get('detail', 'N/A'))
else:
response.raise_for_status()
return resp_json
def request_api(client):
response = client.http_request('GET', '')
return response
# initial flow of execution
def main():
client = Client()
print(request_api(client))
if __name__ in ('__main__', '__builtin__', 'builtins'):
main()
MyApp_test.py
from unittest import mock
def test_api_failure():
from mocking.MyApp import request_api
# lots of complexities here that we have to mock this object
client = mock.Mock()
client.http_request.call_real_method # something that I want to achieve.
client.my_requests.request.return_value = '{"status":"ok"}'
request_api(client)
It's clear that creating an object to call the method is not possible as object creation requires a lot of arguments.
I have a python flask app that is receiving webhook from another application. When it receives the webhook, it responds back by carry out a task (looking up someone's availability) and responding back to the web application with a response. I am getting an unbound local error local variable 'response' referenced below assignment when sending a response back. It looks like calling response at that level is causing issues.
Any help would be greatly appreciated.
from flask import Flask
from flask import request
from flask import make_response
import logging
import json
import random
import os
import importlib
import win32com.client
import pywintypes
import datetime
import pythoncom
from gevent.pywsgi import WSGIServer
from gevent import monkey; monkey.patch_all()
import string
pythoncom.CoInitialize()
logger = logging.getLogger()
logger.setLevel(logging.INFO)
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(filename)s - %(funcName)s - %(message)s')
app = Flask(__name__)
#app.route('/webhook', methods=['POST'])
def webhook():
req = request.get_json(silent=True, force=True)
logger.info("Incoming request: %s", req)
intent = get_intent_from_req(req)
logger.info('Detected intent %s', intent)
if intent == "Check Schedule Next":
pythoncom.CoInitialize()
emailparam = req.get('queryResult').get('parameters').get('email')
datetime1 = req.get('queryResult').get('parameters').get('date-time').get("date_time")
datetime2=datetime1.replace('T',' ')
datetime3=datetime2.replace("-04:00", "")
print(datetime3)
pythoncom.CoInitialize()
class MeetingRoom:
def __init__(self, inputDate, duration, locationMail):
self.inputDate = inputDate
self.oOutlook = win32com.client.Dispatch("Outlook.Application")
self.bookings = self.oOutlook.CreateItem(1)
self.bookings.Start = inputDate
self.bookings.Duration = duration
self.bookings.Subject = 'Follow Up Meeting'
self.bookings.MeetingStatus = 1
self.roomRecipient = self.bookings.Recipients.Add(locationMail)
def checkRoomAvailability(self):
bookingDateTime = datetime.datetime.strptime(self.inputDate, '%Y-%m-%d %H:%M:%S')
self.roomRecipient.resolve
myDate = bookingDateTime.date()
pywintypeDate = pywintypes.Time(myDate)
availabilityInfo = self.roomRecipient.FreeBusy(pywintypeDate, self.bookings.Duration, True)
timeAvailability = []
newTime = pywintypeDate
# print(newTime)
currentTime = datetime.datetime.now()
for isAvailable in availabilityInfo:
# print(newTime, " :: ", isAvailable)
if isAvailable == "0" and newTime > currentTime:
timeAvailability.append(newTime)
newTime = newTime + datetime.timedelta(minutes=self.bookings.Duration)
# print(availabilityInfo)
# for value in timeAvailability:
# print(value)
try:
index = timeAvailability.index(bookingDateTime)
print(emailparam, "is available")
response = {
'fulfillmentText': emailparam
}
# self.bookings.Save()
# self.bookings.Send()
except ValueError:
for timestamp in timeAvailability:
if bookingDateTime <= timestamp:
break
print("I dont see availability for", emailparam, "at", bookingDateTime, " but next available time is ", timestamp)
x = ("I dont see availability for", emailparam, "at", bookingDateTime, " but next available time is ", timestamp)
response = {
'fulfillmentText': x
}
# def bookMeetingRoom():
if __name__ == '__main__':
meetingRoomObj = MeetingRoom(datetime3, 15, emailparam)
meetingRoomObj.checkRoomAvailability()
#response = {
# 'fulfillmentText': emailparam
#}
res = create_response(response)
return res
def get_intent_from_req(req):
try:
intent_name = req['queryResult']['intent']['displayName']
except KeyError:
return None
return intent_name
def get__from_req(req):
try:
intent_name = req['queryResult']['intent']['displayName']
except KeyError:
return None
return intent_name
def create_response(response):
res = json.dumps(response, indent=4)
logger.info(res)
r = make_response(res)
r.headers['Content-Type'] = 'application/json'
return r
if __name__ == '__main__':
LISTEN = ('0.0.0.0',8080)
http_server = WSGIServer( LISTEN, app )
http_server.serve_forever()
This line references response before it's initialized:
res = create_response(response)
Perhaps make sure all code paths initialize the response varaiable?
Solution
It seems you've created your response object in the wrong scope, remove it from the function checkRoomAvailability.
Inside the function checkRoomAvailability after you've created the response object, return it like so
response = {
'fulfillmentText': x
}
return response #ADD THIS LINE
Remove these lines
if __name__ == '__main__':
meetingRoomObj = MeetingRoom(datetime3, 15, emailparam)
meetingRoomObj.checkRoomAvailability()
Then add back the object creation and call right before you create your response like so
meetingRoomObj = MeetingRoom(datetime3, 15, emailparam)
response = meetingRoomObj.checkRoomAvailability()
res = create_response(response)
return res
Suggestion
You are lacking some fundamental understanding about how python or scope works so I suggest taking a read friend
https://docs.python.org/3.3/reference/executionmodel.html
How to get logged into some website using python code
i.e www.example.com/auth/gmail which is taking advantage of google+ API for user logins. Now I would like to login with my credentials (Gmail or What?) by using python code. Please help me how to approach towards this problem.
Thanks
Here you have an example by using the google-api-python-client
First of all you have to create your client secrets on the google developer console.
First time you execute the code you will have to authorize the script to use your gmail account, then you can save the credentials on a file as on the example, and use it for the future executions without requiring this authentication
from googleapiclient.discovery import build
from oauth2client import client
from googleapiclient.errors import HttpError
import base64
from email.mime.text import MIMEText
from apiclient import errors
from oauth2client import client
import httplib2
from googleapiclient.discovery import build
def getCredentials(secrets, scope,filename):
flow = client.flow_from_clientsecrets(
secrets,
scope=scope,
redirect_uri='urn:ietf:wg:oauth:2.0:oob')
auth_uri = flow.step1_get_authorize_url()
webbrowser.open(auth_uri)
auth_code = raw_input('Enter the auth code: ')
credentials = flow.step2_exchange(auth_code)
saveJson(filename,credentials.to_json())
def saveJson(filename, object):
with open(filename, 'w') as f:
json.dump(object, f)
def openJson(filename):
with open(filename, 'r') as f:
object = json.load(f)
return object
if __name__=='__main__':
client_secrets = 'client_secrets.json' #client secrets to use the API
credentials = 'auth_credentials.json'
if(firstRun) #create a file with the auth credentials
scope = 'https://www.googleapis.com/auth/gemail.send'
getCredentials(secrets,scope,credentials)
cre = client.Credentials.new_from_json(openJson(credentials))
http_auth = cre.authorize(httplib2.Http())
gmail = build('gmail', 'v1', http=http_auth)
#gmail.doSomething
this is old(sandbox) and is done really fast so, you have to refactor the code
import re
import sys
import imaplib
import getpass
import email
import datetime
import string
import get_mail_search
from sys import stdout
M = imaplib.IMAP4_SSL('imap.gmail.com')
class Get_mail(object):
"""docstring for Get_mail"""
def __init__(self, *args):
super(Get_mail, self).__init__()
c=1
self.login(c)
self.toast_msg()
raw_input()
def toast_msg(self, *args):
"""docstring for Get_mail"""
M = self.mailbox()
stdout.write("\n{}\n".format(get_mail_search.search_help_info))
serach_input = raw_input()
rv, data = M.search(None, serach_input)
if rv != 'OK':
print "No messages found!"
id_ls = data[0].split()
rev_id_ls = [i for i in reversed(id_ls)]
if rev_id_ls:
for o in rev_id_ls:
try:
msg_content = self.process_mailbox(M, o)
_date_ = msg_content[0]
_from_ = msg_content[1]
_to_ = msg_content[2]
_subject_ = msg_content[3]
_msg_ = msg_content[4]
stdout.write("$$$$$$$$$$$\nDate: {}\nFrom: {}\nTo: {}\nSubject: {}\nMSG: {}\n".format(_date_,_from_,_to_,_subject_,_msg_))
except Exception, e:
pass
else:
stdout.write("No {} Mail Found!".format(serach_input))
raw_input()
self.toast_msg()
def login(self, try_c, *args):
"""docstring for Get_mail"""
try:
stdout.write("\nMail:\n")
mail = raw_input()
if mail:
M.login(str(mail), getpass.getpass())
else:
sys.exit(1)
except imaplib.IMAP4.error:
if try_c<=3:
stdout.write("Versuch: {}/3\n".format(try_c))
stdout.write("Die eingegebene E-Mail-Adresse und das Passwort stimmen nicht uberein. Nochmal versuchen")
try_c+=1
self.login(try_c)
else:
sys.exit(1)
def mailbox(self, *args):
"""docstring for Get_mail"""
rv, mailboxes = M.list()
if rv == 'OK':
for menu in mailboxes:
print('{}'.format(menu))
rv, data = M.select("inbox")
if rv == 'OK':
return M
def eval_decode(self, header, *args):
"""docstring for Get_mail"""
return email.Header.decode_header(header)[0]
def process_mailbox(self, M, num, *args):
"""docstring for Get_mail"""
rv, header = M.fetch(num, '(RFC822)')
if rv != 'OK':
print "ERROR getting message", num
header_msg = email.message_from_string(header[0][1])
if header_msg.is_multipart():
body=[payload.get_payload(decode=True) for payload in header_msg.get_payload()]
else:
body=payload.get_payload(decode=True)
from_decode = self.eval_decode(header_msg['From'])
subject_decode = self.eval_decode(header_msg['Subject'])
date_decode = self.eval_decode(header_msg['Date'])
to_decode = self.eval_decode(header_msg['To'])
return (date_decode[0], from_decode[0], to_decode[0], subject_decode[0], str(body[0]))
def run():
try:
Get_mail()
except KeyboardInterrupt:
M.close()
M.logout()
sys.exit(1)
run()
Just a little question : it's possible to force a build in Buildbot via a python script or command line (and not via the web interface) ?
Thank you!
If you have a PBSource configured in your master.cfg, you can send a change from the command line:
buildbot sendchange --master {MASTERHOST}:{PORT} --auth {USER}:{PASS}
--who {USER} {FILENAMES..}
You can make a python script using the urlib2 or requests library to simulate a POST to the web UI
import urllib2
import urllib
import cookielib
import uuid
import unittest
import sys
from StringIO import StringIO
class ForceBuildApi():
MAX_RETRY = 3
def __init__(self, server):
self.server = server
cookiejar = cookielib.CookieJar()
self.urlOpener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookiejar))
def login(self, user, passwd):
data = urllib.urlencode(dict(username=user,
passwd=passwd))
url = self.server + "login"
request = urllib2.Request(url, data)
res = self.urlOpener.open(request).read()
if res.find("The username or password you entered were not correct") > 0:
raise Exception("invalid password")
def force_build(self, builder, reason, **kw):
"""Create a buildbot build request
several attempts are created in case of errors
"""
reason = reason + " ID="+str(uuid.uuid1())
kw['reason'] = reason
data_str = urllib.urlencode(kw)
url = "%s/builders/%s/force" % (self.server, builder)
print url
request = urllib2.Request(url, data_str)
file_desc = None
for i in xrange(self.MAX_RETRY):
try:
file_desc = self.urlOpener.open(request)
break
except Exception as e:
print >>sys.stderr, "error when doing force build", e
if file_desc is None:
print >>sys.stderr, "too many errors, giving up"
return None
for line in file_desc:
if 'alert' in line:
print >>sys.stderr, "invalid arguments", url, data_str
return None
if 'Authorization Failed' in line:
print >>sys.stderr, "Authorization Failed"
return
return reason
class ForceBuildApiTest(unittest.TestCase):
def setUp(self):
from mock import Mock # pip install mock for test
self.api = ForceBuildApi("server/")
self.api.urlOpener = Mock()
urllib2.Request = Mock()
uuid.uuid1 = Mock()
uuid.uuid1.return_value = "myuuid"
sys.stderr = StringIO()
def test_login(self):
from mock import call
self.api.login("log", "pass")
self.assertEquals(len(self.api.urlOpener.open.call_args_list), 1)
req = urllib2.Request.call_args_list
self.assertEquals([call('server/login', 'passwd=pass&username=log')], req)
def test_force(self):
from mock import call
self.api.urlOpener.open.return_value = ["blabla"]
r = self.api.force_build("builder1", reason="reason", param1="foo", param2="bar")
self.assertEquals(len(self.api.urlOpener.open.call_args_list), 1)
req = urllib2.Request.call_args_list
self.assertEquals([call('server//builders/builder1/force', 'reason=reason+ID%3Dmyuuid¶m2=bar¶m1=foo')], req)
self.assertEquals(r, "reason ID=myuuid")
def test_force_fail1(self):
from mock import call
self.api.urlOpener.open.return_value = ["alert bla"]
r = self.api.force_build("builder1", reason="reason", param1="foo", param2="bar")
self.assertEquals(len(self.api.urlOpener.open.call_args_list), 1)
req = urllib2.Request.call_args_list
self.assertEquals([call('server//builders/builder1/force', 'reason=reason+ID%3Dmyuuid¶m2=bar¶m1=foo')], req)
self.assertEquals(sys.stderr.getvalue(), "invalid arguments server//builders/builder1/force reason=reason+ID%3Dmyuuid¶m2=bar¶m1=foo\n")
self.assertEquals(r, None)
def test_force_fail2(self):
from mock import call
def raise_exception(*a, **kw):
raise Exception("oups")
self.api.urlOpener.open = raise_exception
r = self.api.force_build("builder1", reason="reason", param1="foo", param2="bar")
req = urllib2.Request.call_args_list
self.assertEquals([call('server//builders/builder1/force', 'reason=reason+ID%3Dmyuuid¶m2=bar¶m1=foo')], req)
self.assertEquals(sys.stderr.getvalue(), "error when doing force build oups\n"*3 + "too many errors, giving up\n")
self.assertEquals(r, None)
def test_force_fail3(self):
from mock import call
self.api.urlOpener.open.return_value = ["bla", "blu", "Authorization Failed"]
r = self.api.force_build("builder1", reason="reason", param1="foo", param2="bar")
req = urllib2.Request.call_args_list
self.assertEquals([call('server//builders/builder1/force', 'reason=reason+ID%3Dmyuuid¶m2=bar¶m1=foo')], req)
self.assertEquals(sys.stderr.getvalue(), "Authorization Failed\n")
self.assertEquals(r, None)
if __name__ == '__main__':
unittest.main()