Simple beginner stuff, multiple conditional test - python

ok, this seems like it should be really simple but Im a bit confused:
i have two values - domain and ip
its best described with code:
whois_result = Popen(['whois', str(domain)], stdout=PIPE,stderr=STDOUT).communicate()[0]
debug_output(whois_result)
if 'Not found' or 'No entries' in whois_result:
print "Processing whois failure on '%s'" % str(domain)
print "Trying the IP (%s) instead..." % ip
whois_result = Popen(['whois', ip], stdout=PIPE,stderr=STDOUT).communicate()[0]
debug_output(whois_result)
if 'Not found' or 'No entries' in whois_result:
print "complete and utter whois failure, its you isnt it, not me."
return False
else:
test = re.search("country.+([A-Z].)",whois_result)
countryid = test.group(1)
so this function checks the domain whois, if it doesnt find it, its tries a whois with the ip address, but what I want to know is what is the best way to check if the domain is equal to None dont bother with the domain check and go onto the ip check, yet also if the domain is NOT equal to None, do the domain check and then the ip check in that order. Sorry if this is basic, this has me a bit confused. I guess i could set a variable and test for that but is there a more elegant way of doing it ?
if i put at the top a
if domain != None:
the only way it seems i can do it is by repeating the code or setting a variable, I guess there must be other conditional tests I could use that I dont know about.
EDIT: update 2 based on answers below: - ive also put in the country checking code with my database.
def do_whois(data):
if data is not None: return Popen(['whois', str(data)], stdout=PIPE,stderr=STDOUT).communicate()[0]
return 'No entries'
def check_whois(data):
conn = sqlite3.connect(db_name)
cursor = conn.cursor()
if 'No entries' in data or 'Not found' in data or 'No match for' in data:return False
id = re.search("country.+([A-Z].)",data)
if id is None:
print "we didnt get nuttin from whois"
return False
countryid = id.group(1)
# fetch country from countrycode db
cursor.execute("SELECT country,countrycode FROM countries WHERE countrycode = ?",(countryid,))
country = cursor.fetchone()
country = country[0]
print "Server is from: " + country
return (country,countryid)
def find_country(domain, ip):
return check_whois(do_whois(domain)) or check_whois(do_whois(ip))
part of the problem with making this robust is the varying values returned by the whois server eg for this IP: 67.222.137.216
the whois server returns :
# : whois 67.222.137.216
#
# Query terms are ambiguous. The query is assumed to be:
# "n 67.222.137.216"
#
# Use "?" to get help.
#
#
# The following results may also be obtained via:
# http://whois.arin.net/rest/nets;q=67.222.137.216?showDetails=true&showARIN=false&ext=netref2
#
BLUESQUAREDATAVPSLLC BLUESQUAREDATAVPSLLCNET (NET-67-222-137-213-1) 67.222.137.213 - 67.222.137.244
DFW Datacenter DFW-DATACENTER (NET-67-222-128-0-1) 67.222.128.0 - 67.222.159.255
#
# ARIN WHOIS data and services are subject to the Terms of Use
# available at: https://www.arin.net/whois_tou.html
#
thanks for any help.

Try this
def do_whois(data):
if data: return Popen(['whois', str(data)], stdout=PIPE,stderr=STDOUT).communicate()[0]
return 'No entries'
def check_whois(data):
if 'No entries' in data or 'Not found' in data:return False
test = re.search("country.+([A-Z].)",whois_result)
return test.group(1)
def find_whois(domain, ip):
return check_whois(do_whois(domain)) or check_whois(do_whois(ip))

This isn't going to work :
if 'Not found' or 'No entries' in whois_result:
This is interpreted as if ('Not found') or ('No entries' in whois_result) which always returns True.
To answer your question:
if domain != None && domain != 1:
-edit-
If you meant None instead of "one", you should simply put your IP checking code (which is to be executed after the domain check) on the same indenting level as the domain check.

This condition is wrong:
if 'Not found' or 'No entries' in whois_result:
It will always evaluate as "true", because the expression 'Not found' or 'No entries' in whois_result will always return 'Not found'.
You need to changed the if-statement to:
if 'Not found' in whois_result or 'No entries' in whois_result:

Related

Django - checking if instance exists results in internal server error 500

I am trying to check if I have an entry in my database using this code:
def device_update(request):
json_data = json.loads(request.body)
email = json_data['email']
imei = json_data['imei']
sdk_version = json_data['sdk_version']
date = json_data['updateDate']
rule = json_data['ruleName']
group_name = json_data['group']
if Group.objects.filter(group=group_name).exists():
print("group does exists")
else:
print("group doesn't exists")
return HttpResponse("Successful")
However, when the code reaches the if statement to check if the group exists, it returns error 500.
I tried to check with two groups one that exists and another one that doesn't, in both cases I got error 500.
How can I fix this and why is this happening?
The logic for checking if a Group exists, i.e. the line:
if Group.objects.filter(group=group_name).exists()
is not throwing the error here. It is likely that json_data is missing one of the keys you expect it to have, for example, 'group'.
I'd recommend using the get method that dictionaries have. This provides default values when the specified key is not present in the dictionary. You should also have error handling for when the request body is not in valid JSON format.
Here's an example:
def device_update(request):
try:
json_data = json.loads(request.body)
except json.JSONDecodeError:
return HttpResponse('Request body must be in valid JSON format')
email = json_data.get('email', '')
imei = json_data.get('imei', '')
sdk_version = json_data.get('sdk_version', '')
date = json_data.get('updateDate', '')
rule = json_data.get('ruleName', '')
group_name = json_data.get('group', '')
if Group.objects.filter(group=group_name).exists():
print("group does exists")
else:
print("group doesn't exists")
return HttpResponse("Successful")
I set the defaults to the empty string '', but you may want to change that.
Your view doesn't have any error handling. Looking at it quickly, at least two things could go wrong. The request body might not be valid json, and if it is valid json, it might not contain the required keys.
def device_update(request):
try:
json_data = json.loads(request.body)
except ValueError:
return HttpResponse("Invalid json")
try:
email = json_data['email']
imei = json_data['imei']
sdk_version = json_data['sdk_version']
date = json_data['updateDate']
rule = json_data['ruleName']
group_name = json_data['group']
except KeyError as e:
return HttpResponse("Missing Key %s" % e[0])
...
Writing your own validation for a single view like this is ok. As it gets more complicated, you might want to look at django rest framework. It has serializers which will help you manage validation.
Alasdair/Keselme, looks that your view is correct.
Try to put the ipdb into your code in order to debug your code, and than you can print the request.data and see what is comming in the request.

Python Geolocator Geocode location in None but still works + random string is added (weirdest error I ever saw)

I have at the moment to figure out where "favicon.ico" comes from. It is really super weird.
I use geopy to geocode a location into latitude and longitude, then I use these values to create markers on a google map (Flask GoogleMaps).
That is the piece of code:
try:
print findroomcity
location = geolocator.geocode(findroomcity)
print location, location.latitude, location.longitude
if location:
mymap = Map(
identifier="view-side",
lat=location.latitude,
lng=location.longitude,
markers=[(location.latitude, location.longitude)],
zoom = 12
)
else:
print "location is none"
In this case findroomcity is "dortmund". It is actually grabbed from a form.
If I submit the form the map is actually created, so it does not use the else block But it tells me that location in NoneType and has no attribute latitude. It seems that it calls the try block three times and the first time findroomcity is "favicon.ico", also the last time
Check the outputs of the prints:
I dont even used "favicon.ico" in my whole project, I know it must be somewhere but I checked every .py file and also searched for every print. I am really super confused, I keep searching, but maybe someone has encountered something similar.
Here is the whole method which creates the map:
# Die Filter Funktion mit Google Maps
#app.route('/<findroomcity>', methods=["GET", "POST"])
def find_room(findroomcity):
form = FilterZimmerForm()
if form.validate_on_submit():
query = Zimmer.query
filter_list = ["haustiere_erlaubt","bettwaesche_wird_gestellt","grill_vorhanden","safe_vorhanden","kuehlschrank_vorhanden","rauchen_erlaubt","parkplatz_vorhanden",
"kochmoeglichkeit_vorhanden","restaurant_im_haus_vorhanden","handtuecher_werden_gestellt","tv_vorhanden","waschmoeglichkeit_vorhanden","wlan_vorhanden"]
for filter_name in filter_list:
if getattr(form, filter_name).data:
query = query.filter(getattr(Zimmer, filter_name).is_(True))
all_rooms_in_city = query.all()
else:
all_rooms_in_city = Zimmer.query.order_by(desc("stadt")).all()
try:
print findroomcity
location = geolocator.geocode(findroomcity)
print location, location.latitude, location.longitude
if location:
mymap = Map(
identifier="view-side",
lat=location.latitude,
lng=location.longitude,
markers=[(location.latitude, location.longitude)],
zoom = 12
)
else:
print "location is none"
except AttributeError as e:
flash("Ort nicht gefunden")
print e
return redirect(url_for('index'))
except GeocoderTimedOut as e:
print e
sleep(1)
return render_template('zimmer_gefunden.html', mymap=mymap, all_rooms_in_city=all_rooms_in_city, findroomcity=findroomcity, form=form)
EDIT
I have really no idea where it comes from, I use now:
if location.latitude is not None:

Bad search filter

Im trying to filter few attributes from the ldap server but get errors,
ldap.FILTER_ERROR: {'desc': 'Bad search filter'}
Code:-
import ldap
ldap.OPT_REFERRALS = 0
ldap_server="ldapps.test.com"
username = "testuser"
password= "" #your password
connect = ldap.open(ldap_server)
dn='uid='+username;
print 'dn =', dn
try:
result = connect.simple_bind_s(username,password)
print 'connected == ', result
filter1 = "(|(uid=" + username + "\*))"
result = connect.search("DC=cable,DC=com,DC=com",ldap.SCOPE_SUBTREE,filter1)
print result
except ldap.INVALID_CREDENTIALS as e:
connect.unbind_s()
print "authentication error == ", e
Your search filter is, in fact, bad.
The | character is for joining several conditions together in an OR statement. For example, if you wanted to find people with a last name of "smith", "jones", or "baker", you would use this filter:
(|(lastname=smith)(lastname=jones)(lastname=baker))
However, your filter only has one condition, so there's nothing for the | character to join together. Change your filter to this and it should work:
"(uid=" + username + "\*)"
By the way, what are you trying to do with the backslash and asterisk? Are you looking for people whose usernames actually end with an asterisk?

ConfigObj option validation

I am using ConfigObj and Validator to parse a configuration file in python. While I like this tool a lot, I am having trouble with validation using a configSpec file. I am using the option() configSpec type that forces the value to be chosen from a controlled vocabulary:
output_mode = option("Verbose", "Terse", "Silent")
I want my code to know when the user enters an option that's not in the CV. From what I have fond, Validator only seems to say which config key failed validation, but not why it failed:
from configobj import ConfigObj, flatten_errors
from validate import Validator
config = ConfigObj('config.ini', configspec='configspec.ini')
validator = Validator()
results = config.validate(validator)
if results != True:
for (section_list, key, _) in flatten_errors(config, results):
if key is not None:
print 'The "%s" key in the section "%s" failed validation' % (key, ', '.join(section_list))
else:
print 'The following section was missing:%s ' % ', '.join(section_list)
That code snippet works but there are any number of reasons why a key might have failed validation, from not being in an integer range to not being in the CV. I don't want to have to interrogate the key name and raise a different kind of exception depending on the failure cases for that key. Is there a cleaner way to handle specific types of validation errors?
Long time stackoverflow reader, first time poster :-)
Update: I think this does what I want to do. The key is that config obj stores errors as Exceptions which can then be checked against those that subclass ValidateError. Then you just have to do one check per subclass rather than one check per parameter value. It might be nicer if validate just threw an exception if validation failed but maybe you would lose other functionality.
self.config = configobj.ConfigObj(configFile, configspec=self.getConfigSpecFile())
validator = Validator()
results = self.config.validate(validator, preserve_errors=True)
for entry in flatten_errors(self.config, results):
[sectionList, key, error] = entry
if error == False:
msg = "The parameter %s was not in the config file\n" % key
msg += "Please check to make sure this parameter is present and there are no mis-spellings."
raise ConfigException(msg)
if key is not None:
if isinstance(error, VdtValueError):
optionString = self.config.configspec[key]
msg = "The parameter %s was set to %s which is not one of the allowed values\n" % (key, self.config[key])
msg += "Please set the value to be in %s" % optionString
raise ConfigException(msg)
OptionString is just a string of the form option("option 1", "option 2") rather than a list so to get this to look nice, you need to grab the substring in the ()'s.
For future reference for anyone interested, you could also check for extraneous data. This can be handled with the get_extra_values function. The complete example shown below hence does:
load the configuration with validator
look for all the validated errors
verify extra values
from configobj import ConfigObj, ConfigObjError, flatten_errors, get_extra_values
from validate import Validator, VdtValueError
def load_config(configfile, configspec, raise_exception=True):
"Load and check configvale acccording to spec"
config = ConfigObj(configfile, file_error=True, configspec=configspec)
validator = Validator()
results = config.validate(validator, preserve_errors=True)
msg = ""
fatalerr = False
for entry in flatten_errors(config, results):
[sectionList, key, error] = entry
if error is False:
msg += f"\n{key:>30s} missing in section [{']['.join(sectionList)}]"
fatalerr = True
if key is not None:
if isinstance(error, VdtValueError):
optionString = config.configspec[key]
msg += f"\nThe parameter {key} was set to {[config[s][key] for s in sectionList]} which is not one of the allowed values\n"
msg += " Please set the value to be in %s" % optionString
fatalerr = True
# verifying extra values below
wmsg = ""
for sections, name in get_extra_values(config):
# this code gets the extra values themselves
the_section = config
for section in sections:
the_section = the_section[section]
# the_value may be a section or a value
the_value = the_section[name]
section_or_value = 'value'
if isinstance(the_value, dict):
# Sections are subclasses of dict
section_or_value = 'section'
section_string = '[' + (']['.join(sections) or "TOP LEVEL") + ']'
wmsg += f"\n{name:>30s}: Extra {section_or_value} on section {section_string}"
if wmsg != "":
print(f"\nWARNINGS found in configuration file {configfile}")
print(wmsg)
if fatalerr:
print(f"\nERRORS found in configuration file {configfile}")
if raise_exception:
raise RuntimeError(msg)
else:
print("Fatal errors found, but no exception raised, as requested")
print(msg)
print(f'Configuration {configfile} validated successfully')
return config
if __name__ == "__main__":
configfile="xt_default.cfg"
configspec="xt_default_spec.cfg"
config = load_config(configfile, configspec)

How do I catch "split" exceptions in python?

I am trying to parse a list of email addresses to remove the username and '#' symbol only leaving the domain name.
Example: blahblah#gmail.com
Desired output: gmail.com
I have accomplished this with the following code:
for row in cr:
emailaddy = row[0]
(emailuser, domain) = row[0].split('#')
print domain
but my issue is when I encounter a improperly formatted email address. For example if the row contains "aaaaaaaaa" (instead of a valid email address) the program crashes with the error
(emailuser, domain) = row[0].split('#')
ValueError: need more than 1 value to unpack.
(as you would expect) Rather than check all the email addresses for their validity, I would rather just not update grab the domain and move on to the next record. How can I properly handle this error and just move on?
So for the list of:
blahblah#gmail.com
mmymymy#hotmail.com
youououou
nonononon#yahoo.com
I would like the output to be:
gmail.com
hotmail.com
yahoo.com
Thanks!
You want something like this?
try:
(emailuser, domain) = row[0].split('#')
except ValueError:
continue
You can just filter out the address which does not contain #.
>>> [mail.split('#')[1] for mail in mylist if '#' in mail]
['gmail.com', 'hotmail.com', 'yahoo.com']
>>>
What about
splitaddr = row[0].split('#')
if len(splitaddr) == 2:
domain = splitaddr[1]
else:
domain = ''
This even handles cases like aaa#bbb#ccc and makes it invalid ('').
Try this
In [28]: b = ['blahblah#gmail.com',
'mmymymy#hotmail.com',
'youououou',
'nonononon#yahoo.com']
In [29]: [x.split('#')[1] for x in b if '#' in x]
Out[29]: ['gmail.com', 'hotmail.com', 'yahoo.com']
This does what you want:
import re
l=["blahblah#gmail.com","mmymymy#hotmail.com",
"youououou","nonononon#yahoo.com","amy#bong#youso.com"]
for e in l:
if '#' in e:
l2=e.split('#')
print l2[-1]
else:
print
Output:
gmail.com
hotmail.com
yahoo.com
youso.com
It handles the case where an email might have more than one '#' and just takes the RH of that.
if '#' in row[0]:
user, domain = row[0].split('#')
print domain
Maybe the best solution is to avoid exception handling all together.
You can do this by using the builtin function partition(). It is similar to split() but does not raise ValueError when the seperator is not found. Read more: https://docs.python.org/3/library/stdtypes.html#str.partition
We can consider the string not having '#' symbol, as a simple username:
try:
(emailuser, domain) = row[0].split('#')
print "Email User" + emailuser
print "Email Domain" + domain
except ValueError:
emailuser = row[0]
print "Email User Only" + emailuser
O/P:
Email User : abc
Email Domain : gmail.com
Email User : xyz
Email Domain : gmail.com
Email User Only : usernameonly

Categories