Checking to see if multiple ENV variables exist - python

Is there a more optimal way I can check to see if multiple ENV variables exist with customized exceptions? Perhaps a way to match a group of EVN variables, and then have the exception self-reference the variable name in its output?
if os.environ.get('USERNAME') is not None:
self.username = os.environ.get('USERNAME')
else:
raise CustomException('Environment variable USERNAME not set')
if os.environ.get('PASSWORD') is not None:
self.password = os.environ.get('PASSWORD')
else:
raise CustomException('Environment variable PASSWORD not set')
I am using Python 2.7. Thanks!

You can do something like this:
#
# ENV vars you want to go over
#
env_vars = 'HOME,PATH,NONEXISTS'.split(',')
for evar in env_vars:
# Loop will create it as: self.$evar = os.environ.get(evar)
if evar not in os.environ:
# Will skip: NONEXISTS
continue
# or if you want to raise exception
raise ValueError('Environment variable "%s" was not set' % evar)
# setattr: will create a dynamic attribute for "self"
# self.home = ...
# self.path = ...
# evar.lower() => so we'll have self.home vs self.HOME
setattr(self, evar.lower(), os.environ.get(evar))
In general, just note that you don't need to verify if it's "None" in Python, so
# Replace this
if os.environ.get('USERNAME') is not None:
# With this, the default of get => is None, and None won't pass "if"
if os.environ.get('USERNAME'):
# Will create an exception if USERNAME doesn't exists
if os.environ['USERNAME']
Hope it helps ...

You could always use a loop with a three items list:
for data in [
["USERNAME", "username", CustomException],
["PASSWORD", "password", CustomException]
]:
env_var = os.environ.get(data[0])
if env_var:
setattr(self, data[1], env_var)
else:
# Should work, cannot check due to not having actually Python installed.
raise data[2]("Environment variable %s not set" % data[0])
If you don't like using indexes, you could replace the items by dicts like this to have a more consistent access if you change order:
{"env_var_name": "USERNAME", "attr": "username", "exception_cls": CustomException}

Just put all the environment lookups in a try: block:
try:
self.username= os.environ['USERNAME']
self.password= os.environ['PASSWORD']
except KeyError as e:
raise CustomException('Environment variable {} not set'.format(e.args[0]))

Related

Python: How to Handle the Exception to Class variable

I have no idea to implement to handle the class variable exception. I am trying to create python module which has dependency with mongodb.
class HrmLookUps(DBMixin):
db_handle = DBMixin.get_db_handle(DBMixin, MONGO_STORE_DICT.get("DB_NAME"),
MONGO_STORE_DICT.get("DB_HOST"),
MONGO_STORE_DICT.get("DB_PORT"),
MONGO_STORE_DICT.get("USERNAME"),
MONGO_STORE_DICT.get("PASSWORD"))
#classmethod
def get_gender(cls):
collection_name = COLLECTION_NAME_DICT.get("COLLECTION_GENDER")
# collection_name = "departments"
gender_record = cls.get_from_db(cls, cls.db_handle, collection_name)
if gender_record[collection_name]:
return gender_record
else:
raise KeyError("Collection Name Invalid!")
I have multiple get method like above get_gender(). I am handling each method raised Keyerror if its data empty.
My question is,
Is this proper way to handle exception of methods?
If my class variable has some issues ex.database credential wrong how can I handle that?
Currently your else clause isn't really doing anything. Your if statement would already throw an error if collection_name wasn't a key in gender_record. So unless you want to raise KeyError in the else clause when collection_name is in gender_record but its value happens to be 0 or False or None.
I think what you are trying to do is something closer to these examples:
#classmethod
def get_gender(cls):
collection_name = COLLECTION_NAME_DICT.get("COLLECTION_GENDER")
# collection_name = "departments"
gender_record = cls.get_from_db(cls, cls.db_handle, collection_name)
if collection_name in gender_record:
return gender_record
else:
raise KeyError("Collection Name Invalid!")
or this maybe
#classmethod
def get_gender(cls):
collection_name = COLLECTION_NAME_DICT.get("COLLECTION_GENDER")
# collection_name = "departments"
gender_record = cls.get_from_db(cls, cls.db_handle, collection_name)
try:
gender_record[collection_name]
return gender_record
else KeyError as err:
raise KeyError("Collection Name Invalid!") from err
Handling exceptions is pretty much the same in any situation. so for the credentials it would be something like this:
try:
db_handle = DBMixin.get_db_handle(DBMixin, MONGO_STORE_DICT.get("DB_NAME"),
MONGO_STORE_DICT.get("DB_HOST"),
MONGO_STORE_DICT.get("DB_PORT"),
MONGO_STORE_DICT.get("USERNAME"),
MONGO_STORE_DICT.get("PASSWORD"))
except <SomeCredentialErrorHere>:
# whatever you put here is what gets executed if the error is raised.

python3 function not defined even though it is

when I try to call the changeProfile function, I keep getting the error "getAuthCode is not defined" even though it is clearly defined. Why do I keep getting this error? What am I doing wrong? It used to work from what I remember, but now all of a sudden it doesn't. Any help would be appreciated :)
import os,re,json,socket,random,select,threading,time,sys
import urllib.request as urlreq
from urllib.request import quote,unquote
import urllib.parse
class miscellanous:
"""Main class."""
def __init__():
"""What to do on initalizing."""
pass
def getAuthCode(u, p):
"""Get authentification code from username and password specified."""
try:
data=urllib.request.urlopen('http://chatango.com/login',urllib.parse.urlencode({'user_id': u, 'password': p, 'storecookie': 'on', 'checkerrors': 'yes'}).encode()).headers
except Exception as e: print("Error: Auth request: %s" % e)
for x, y in data.items():
if x.lower() == 'set-cookie':
returned = re.compile(r"auth\.chatango\.com ?= ?([^;]*)", re.IGNORECASE).search(y)
if returned:
ret = returned.group(1)
if ret == "": raise ValueError("Error: Unable to get auth: Error in username/password.")
return ret
def createAccount(u, p):
"""Create an account with the username and password specified."""
try:
resp=urllib.request.urlopen("http://chatango.com/signupdir", urllib.parse.urlencode({"email": "accmaker"+str(random.randrange(1,1000000000000))+"#hotmail.com", "login": u, "password": p, "password_confirm": p, "storecookie": "on", "checkerrors": "yes"}).encode())
fu=str(resp.read())
resp.close()
if "screen name has been" in fu: r = "Error: User could not be created: Already exists."
else: r = "The user was created. If it didn't work, try another username."
return r
except: return "Error: Invalid or missing arguments."
def createGroup(u, p, g, d="Description.", m="Owner message."):
"""Creates a group with the username, password, group name, description and owner message specified."""
try:
g=g.replace(" ","-")
resp=urllib.request.urlopen("http://chatango.com/creategrouplogin",urllib.parse.urlencode({"User-Agent": "Mozilla/5.0", "uns": "0", "p": p, "lo": u, "d": d, "u": g, "n": m}).encode())
fu=str(resp.read())
resp.close()
if "groupexists" in fu: r = "Error: Group could not be created: Already exists."
else: r = "The group was created. If it didn't work, try another group name. Click <a href='http://%s.chatango.com/' target='_blank'>[[here]]<a> to get to the new group."
return r
except: return "Error: Invalid or missing arguments."
def changeProfile(u, p, m="Default", e="accmaker"+str(random.randrange(1,1000000000000))+"#hotmail.com", l="Norway", g="M", a="18"):
try:
resp = urlreq.urlopen('http://'+u.lower()+'.chatango.com/updateprofile?&d&pic&s='+getAuthCode(u, p), urllib.parse.urlencode({"show_friends": "checked", "dir": "checked", "checkerrors": "yes", "uns": "1", "line": m, "email": e, "location": l, "gender": g, "age": a}).encode())
return "The profile change was successful."
except Exception as e:
return "%s" % e
def checkOnlineStatus(u):
"""Check if the predefined username is online or offline."""
if "Chat with" in urlreq.urlopen("http://"+u.lower()+".chatango.com").read().decode(): return '<b><font color="#00ff00">Online</font></b>'
else: return "<b><font color='#ff0000'>Offline</font></b>"
resp.close()
def checkUserGender(u):
"""Get the gender for the predefined username."""
resp=urlreq.urlopen("http://st.chatango.com/profileimg/%s/%s/%s/mod1.xml" % (u.lower()[0], u.lower()[1], u.lower()))
try: ru=re.compile(r'<s>(.*?)</s>', re.IGNORECASE).search(resp.read().decode()).group(1)
except: ru="?"
ret=unquote(ru)
resp.close()
if ret=="M": r="Male"
elif ret=="F": r="Female"
elif ret=="?": r="Not specified"
return r
def changeBackGround(u, p, x, transparency=None):
"""Update the user's bg using the predefined username, password and bg color."""
color=quote(x.split()[0])
try: image=x.split()[1]
except: image=None
if color and len(color)==1:
color=color*6
if color and len(color)==3:
color+=color
elif color and len(color)!=6:
return False
if transparency!=None and abs(transparency)>1:
transparency = abs(transparency) / 100
data=urllib.request.urlopen("http://fp.chatango.com/profileimg/%s/%s/%s/msgbg.xml" % (u[0], u[1], u.lower())).read().decode()
data=dict([x.replace('"', '').split("=") for x in re.findall('(\w+=".*?")', data)[1:]])
data["p"]=p
data["lo"]=u
if color: data["bgc"] = color
if transparency!=None: data["bgalp"]=abs(transparency) * 100
if image!=None: data["useimg"]=1 if bool(image) else 0
data12=urllib.parse.urlencode(data)
data13=data12.encode()
der=urllib.request.urlopen("http://chatango.com/updatemsgbg", data13).read()
def checkIfGroupExists(g):
"""Check if the predefined group exists."""
i = urlreq.urlopen('http://'+g+'.chatango.com').read().decode()
if '<table id="group_table"' in i: return True#"This chat does exist!"
else: return False#"This chat doesn't exist."
i.close()
All of the functions you've shown are part of the miscellaneous class, so to access them, you need to prefix them with the class name. To refer to the getAuthCode function, you'd use miscellaneous.getAuthCode.
But, it doesn't seem like you should really be using a class here. You never create instances of miscellaneous, nor are the functions set up to be run as methods. So, probably the right answer is to get rid of the class miscellaneous: declaration at the top of the file, and then to unindent all the functions one level.
(Note, in Python 2 you'd have an additional issue if you kept the class: Unbound methods required that their first argument be an instance of their class (or a subclass). In that situation, you'd need to use the staticmethod decorator on any functions that did not expect to get an instance at all.)
Functions within a Python class are called methods. They normally take a self parameter before their other parameters. Furthermore, methods cannot "see" each other directly; you need to call them as self.method(args) instead of just method(args).

Concise replacement for long list of Try-Except statement in Python?

I have this long list of try except statement:
try:
uri = entry_obj['media$group']['media$content'][0]['url']
except (KeyError, IndexError):
uri = None
try:
position = entry_obj['yt$position']['$t']
except KeyError:
position = None
try:
description = entry_obj['content']['$t']
except KeyError:
description = None
try:
seconds = entry_obj['media$group']['yt$duration']['seconds']
except KeyError:
seconds = None
try:
thumbnails = entry_obj['media$group']['media$thumbnail']
except KeyError:
thumbnails = None
Is there a more concise way to write this?
If you tire of figuring out what to use for default values in get() calls, just write a helper function:
def resolve(root, *keys):
for key in keys:
try:
root = root[key]
except (KeyError, IndexError):
return None
return root
Then you just write, e.g.:
uri = resolve(entry_obj, 'media$group', 'media$content', 0, 'url')
To simplify the calls a little, you might beef up the helper function to take a single string for the keys and split on spaces; that way you don't have to type so many quotes, and we can also add a default value argument:
def resolve(root, keys, default=None):
for key in keys.split():
try:
root = root[key]
except (TypeError, KeyError):
try:
root = root[int(key)]
except (IndexError, ValueError, KeyError):
return default
uri = resolve(entry_obj, 'media$group media$content 0 url', '')
I thought of another good way to do this, not sure how it compares to kindall's method. We first define a method property:
def res(self, property):
try:
return property()
except (KeyError, IndexError):
return None
Then replace the try-except statements with:
url = res(lambda: entry_obj['media$group']['media$content'][0]['url'])
position = res(lambda: entry_obj['yt$position']['$t'])
description = res(lambda: entry_obj['content']['$t'])
duration = res(lambda: entry_obj['media$group']['yt$duration']['seconds'])
thumbnails = res(lambda: entry_obj['media$group']['media$thumbnail'])
Use the get method of dictionaries instead:
position = entry_object.get('yt$position').get('$t')
get will handle the case of a key not existing for you, and give you a (changable) fallback value instead in that case. You'll still need to handle the first IndexError manually, but all the ones that are just except KeyError: will disappear.

Python Function with "Pointers"

Ok, I recently started programming in Python, and I really like it.
However, I have run into a little issue.
I want to be able to define a function to take in some data and assign it to a variable that I designate, rather than have to perform the operation every time I want to submit the value.
Here is a code fragment:
try:
if elem.virtual.tag:
virt = True
temp_asset.set_virtual(True)
except AttributeError:
temp_asset.set_virtual(False)
if virt: #if virtual, get only faction, value, and range for presence
try:
fac = elem.presence.faction #an xml tag (objectified)
except AttributeError:
fac = "faction tag not found"
temp_asset.misload = True
try:
val = elem.presence.value
except AttributeError:
val = "value tag not found"
temp_asset.misload = True
try:
rang = elem.presence.range
except AttributeError:
rang = "range tag not found"
temp_asset.misload = True
#Set presence values
temp_asset.set_presence(fac, val, rang)
The functions set the values, but I want to be able to perform the error checking with something like this:
def checkval(self, variable_to_set, tag_to_use)
try:
variable_to_set = tag_to_use
except AttributeError:
variable_to_set = "tag not found"
temp_asset.misload = True
Is this doable? Let me know if I need to show more code.
Edit: I don't need pointers per se, just anything that works this way and saves typing.
Edit 2: Alternatively, I need a solution of how to check whether an objectified xml node exists (lxml).
Have you tried/looked into the getattr and setattr functions?
For example, assuming these "variables" are object attributes:
def checkval(self, attr, presence, tagstr):
tag = getattr(presence, tagstr, None) # tag = presence."tagstr" or None
setattr(self, attr, tag or 'tag not found') # ?? = presence."tagstr" or 'tag not found'
if tag is None:
self.temp_asset.misload = True
You call it like,
your_object.checkval('fac', elem.presence, 'faction')
Alternatively, you can pre-define these variables and set them default values before you attempt to look up the tags. For example:
class YourObject(object):
_attrmap = {
'fac': 'faction',
'val': 'value',
'rang': 'range',
}
def __init__(self):
# set default values
for attr, tagstr in self._attrmap.items():
setattr(self, attr, '%s tag not found' % tagstr)
def checkval(self, attr, presence):
for attr, tagstr in self._attrmap.items():
tag = getattr(presence, tagstr, None)
if tag is not None:
setattr(self, attr, tag)
else:
self.temp_asset.misload = True

In Django forms, how do I "add" an error into the queue?

def clean(self):
cleaned_data = self.cleaned_data
current_pass = cleaned_data['current_pass']
new_pass = cleaned_data['new_pass']
new_pass2 = cleaned_data['new_pass2']
if current_pass or new_pass or new_pass2:
if not current_pass:
raise forms.ValidationError("- You must enter your current password.")
if not new_pass:
raise forms.ValidationError("- You must enter a new password.")
if not new_pass2:
raise forms.ValidationError("- You must re-confirm your new password.")
return cleaned_data
Right now, I raise my errors. But this means that the other errors won't pop up. it ends the function when I raise the first one. What if I want to have all 3 errors?
A solution could be to bind those errors to the relevant fields, as explained in the docs.
Your code would look like this:
def clean(self):
cleaned_data = self.cleaned_data
current_pass = cleaned_data['current_pass']
new_pass = cleaned_data['new_pass']
new_pass2 = cleaned_data['new_pass2']
if current_pass or new_pass or new_pass2:
if not current_pass:
self._errors["current_pass"] = self.error_class(["- You must enter your current password."])
if not new_pass:
self._errors["new_pass"] = self.error_class(["- You must enter a new password."])
if not new_pass2:
self._errors["new_pass2"] = self.error_class(["- You must re-confirm your new password."])
del cleaned_data["current_pass"]
del cleaned_data["new_pass"]
del cleaned_data["new_pass2"]
return cleaned_data
Please beware that I could not test it personally though.
By using the clean method, you are doing per-form validation. The validator for the whole form has failed.
For individual fields, you should be using the clean_fieldname methods instead of clean which runs after individual field validation.
If you use the clean_fieldname, you can access the errors in forminstance.errors or forminstance.field.errors
def clean_current_pass(self):
data = self.cleaned_data.get('current_pass'):
if not data:
raise forms.ValidationError('- You must enter your current password.')
return data
def clean_new_pass(self):
data = self.cleaned_data.get('new_pass'):
if not data:
raise forms.ValidationError("- You must enter a new password.")
return data
def clean_new_pass2(self):
data = self.cleaned_data.get('new_pass2'):
if not data:
raise forms.ValidationError('- You must re-confirm your new password.')
return data
{{ myform.errors }} would give you all errors in your template.
(This is a Python question not a Django question.)
This is as it should be: when an error is raised it should immediately propagate upwards until it's handled. You can't expect the rest of the function to be evaluated, because the error hasn't been dealt with yet!
Probably the easiest and cleanest method is to rewrite the code:
check = (current_pass, new_pass, new_pass2)
code = ("You must enter your current password.", ...)
err = ''.join(code for i, code in enumerate(codes) if check[i])
if err:
raise forms.ValidationError(err)

Categories