def was_there_was_an_error(self): ''' Returns True if no error ''' # server side error] set1 = [404, 504, 503, 500] set2 = [400, 405, 501] set3 = [500] if self.rest_request.status_code in set1: blueprint( "[-] Server side error - No Image Available in REST response") yellow_bold_print("Error Code".format( self.rest_request.status_code)) return False # "[-] Server side error - No Image Available in REST response" if self.rest_request.status_code in set2: redprint("[-] User error in Image Request") yellow_bold_print("Error Code".format( self.rest_request.status_code)) return False # "[-] User error in Image Request" if self.rest_request.status_code in set3: #unknown error blueprint( "[-] Unknown Server Error - No Image Available in REST response" ) yellow_bold_print("Error Code".format( self.rest_request.status_code)) return False # "[-] Unknown Server Error - No Image Available in REST response" # no error! if self.rest_request.status_code == 200: return True
def dump_compounds(): """ Prints database to screen """ redprint("-------------DUMPING COMPOUNDS------------") records = database.session.query(Compounds).all() for each in records: print(each) redprint("-------------END DATABASE DUMP------------")
def update_db(): """ DUH """ try: database.session.commit() except Exception as derp: print(derp) redprint("[-] Update_db FAILED")
def validate_formula_input(equation_user_input: str): """ :param formula_input: comma seperated values of element symbols :type formula_input: str makes sure the formula supplied to the code is valid user input will be valid only in the form of: eq = "NH4ClO4,Al=>Al2O3,HCl,H2O,N2" note the lack of spaces """ #user_input_reactants = "NH4ClO4,Al" #user_input_products = "Al2O3,HCl,H2O,N2" #equation_user_input = "NH4ClO4,Al=>Al2O3,HCl,H2O,N2" # if it doesn't work, lets see why! try: # validate equation formatting parsed_equation1 = equation_user_input.split("=>")[0] print(parsed_equation1) parsed_equation2 = equation_user_input.split("=>")[1] print(parsed_equation2) try: #validate reactants formatting user_input_reactants = str.split(parsed_equation1, sep=",") except Exception: redprint("reactants formatting") EquationBalancer.user_input_was_wrong("formula_reactants", user_input_reactants) try: #validate products formatting user_input_products = str.split(parsed_equation2, sep=",") except Exception: redprint("products formatting") EquationBalancer.user_input_was_wrong("formula_products", user_input_products) #validate reactants contents for each in user_input_reactants: try: chempy.Substance(each) except Exception: redprint("reactants contents") EquationBalancer.user_input_was_wrong( "formula_reactants", each) #validate products contents for each in user_input_products: try: chempy.Substance(each) except Exception: redprint("products contents") EquationBalancer.user_input_was_wrong( "formula_products", each) # if the inputs passed all the checks EquationBalancer.balance_simple_equation(user_input_reactants, user_input_products) except Exception: redprint("formula validation exception") EquationBalancer.user_input_was_wrong("formula_general", equation_user_input)
def dump_db(): """ Prints database to screen """ redprint("-------------DUMPING DATABASE------------") records1 = database.session.query(Compound).all() records2 = database.session.query(Composition).all() for each in records1, records2: print(each) redprint("------------END DATABASE DUMP------------")
def Compound_by_id(cid_of_compound: str): """ Returns a compound from the local DB Returns FALSE if entry does not exist :param: cid_of_compound """ cid_passed = cid_of_compound try: #return database.session.query(Compound).filter_by(Compound.cid == cid_passed) # * See that right there? "cid" ? return Compound.query.filter_by(cid=cid_passed).first() # SQL-Alchemy interprets that as the record to lookup # it DOES NOT evaluate the contents of a variable # do not forget that! It uses the name as is! The contents do not matter! except Exception as derp: print(derp) redprint("[-] Failure in Compound_by_id") redprint(str(Exception.__cause__)) return False
def internal_local_database_lookup(entity: str, id_of_record: str): """ feed it a formula or CID followed buy "formula" or "cid" or "iupac_name searches by record and entry Returns False and raises and exception/prints exception on error Returns an SQLAlchemy database object if record exists Don't forget this is for compounds only! """ try: greenprint("[+] performing internal lookup") if search_validate(id_of_record): # in pubchem_search_types: kwargs = {id_of_record: entity} lookup_result = Compound.query.filter_by(**kwargs).first() #lookup_result = database.Compound.query.filter_by(id_of_record = entity).first() return lookup_result except Exception as derp: print(derp) redprint("[-] Not in local database") # None if empty return None
def validate_user_input(self, user_input: str, type_of_input: str): """ User Input is expected to be the proper identifier. type of input is one of the following: cid , iupac_name , cas Ater validation, the user input is used in : Pubchem_lookup.do_lookup() Pubchem_lookup.pubchem_lookup_by_name_or_CID() """ import re cas_regex = re.compile('[1-9]{1}[0-9]{1,5}-\d{2}-\d') if search_validate(type_of_input): #in pubchem_search_types: greenprint("user supplied a : " + type_of_input) try: if type_of_input == "cas": greenprint( "[+} trying to match regular expression for CAS") if re.match(cas_regex, user_input): greenprint("[+] Good CAS Number") self.do_lookup(user_input, type_of_input) else: redprint("[-] Bad CAS Number") self.user_input_was_wrong("bad_CAS", user_input) elif type_of_input == "cid" or "iupac_name": self.do_lookup(user_input, type_of_input) else: redprint( "[-] Something really wierd happened inside the validation flow" ) except Exception as derp: redprint("[-] reached the exception ") print(derp) else: self.user_input_was_wrong("input_type", type_of_input)
def __init__(self, record_to_request: str, image_as_base64: bool, input_type="name", temp_file="image"): ############################# # greenprint("[+] Running as Discord Attachment") # greenprint("[+] Not running as Discord Attachment") #print(str(os.environ['DISCORDAPP'])) if image_as_base64 == False: self.filename = temp_file + ".png" if search_validate(input_type): #in pubchem_search_types: greenprint("searching for an image : " + record_to_request) # fixes local code/context to work with url/remote context if input_type == "iupac_name": self.input_type = "name" else: self.input_type = input_type self.request_url = requote_uri("{}/compound/{}/{}/PNG".format(\ API_BASE_URL,self.input_type,record_to_request)) blueprint("[+] Requesting: " + makered(self.request_url)) self.rest_request = requests.get(self.request_url) # redprint("[-] Request failure at local level") # True means no error if self.was_there_was_an_error() == True: # request good # Store image self.image_storage = Image.open( BytesIO(self.rest_request.content)) if image_as_base64 == False: try: greenprint("[+] Saving image as {}".format( self.filename)) self.image_storage.save(self.filename, format="png") except Exception as blorp: redprint( "[-] Exception when opening or writing image file") print(blorp) elif image_as_base64 == True: print(self.rest_request.raw) greenprint("[+] Encoding Image as Base64") self.image_storage = base64.b64encode(self.image_storage) else: redprint("[-] Error with Class Variable self.base64_save") else: redprint("[-] Input type was wrong for Image Search") return None
def add_to_db(thingie): """ Takes SQLAchemy Class_model Objects For updating changes to Class_model.Attribute using the form: Class_model.Attribute = some_var add_to_db(some_var) """ try: database.session.add(thingie) database.session.commit redprint("=========Database Commit=======") print(thingie) redprint("=========Database Commit=======") except Exception as derp: print(derp) redprint("[-] add_to_db() FAILED") print(str(Exception.__cause__))
def __init__(self, record_to_request: str, image_as_base64=True, input_type="name", temp_file="image"): ############################# if search_validate(input_type): #in pubchem_search_types: greenprint("searching for an image : " + record_to_request) # fixes local code/context to work with url/remote context if input_type == "iupac_name": self.input_type = "name" else: self.input_type = input_type self.request_url = requote_uri("{}/compound/{}/{}/PNG".format(\ API_BASE_URL,self.input_type,record_to_request)) blueprint("[+] Requesting: " + makered(self.request_url)) self.rest_request = requests.get(self.request_url) if self.was_there_was_an_error() == False: # request good # Store image # we want an image file if image_as_base64 == False: try: self.filename = temp_file + ".png" greenprint("[+] Saving image as {}".format( self.filename)) self.image_storage = Image.open( BytesIO(self.rest_request.content)) self.image_storage.save(self.filename, format="png") self.image_storage.close() except Exception as derp: redprint( "[-] Exception when opening or writing image file") print(derp) # we want a base64 string elif image_as_base64 == True: self.image_storage = self.encode_image_to_base64( self.image_storage) else: redprint("[-] Error with Class Variable self.base64_save") else: redprint("[-] Input type was wrong for Image Search") return None
class Config(object): if TESTING == True: SQLALCHEMY_DATABASE_URI = TEST_DB SQLALCHEMY_TRACK_MODIFICATIONS = False elif TESTING == False: SQLALCHEMY_DATABASE_URI = LOCAL_CACHE_FILE SQLALCHEMY_TRACK_MODIFICATIONS = False try: chembot_server = Flask(__name__, template_folder=templates) chembot_server.config.from_object(Config) database = SQLAlchemy(chembot_server) database.init_app(chembot_server) except Exception: redprint(Exception.with_traceback) ############################################################################### # from stack overflow #In the second case when you're just restarting the app I would write a #test to see if the table already exists using the reflect method: #db.metadata.reflect(engine=engine) #Where engine is your db connection created using create_engine(), and see #if your tables already exist and only define the class if the table is undefined. #this will clear the everything? database.metadata.clear() ################################################################################
#image_string = 'data:image/png;base64,'+ str(new_lookup.lookup_object.image) #pubchem_embed.set_image(url='data:image/png;base64,{}'.format(str(new_lookup.lookup_object.image))) asdf = Attachment(data='image/png;base64,{}'.format(str(new_lookup.lookup_object.image))) #await ctx.send(content=new_lookup.image, embed=pubchem_embed) await ctx.send(content=asdf, embed=pubchem_embed) @lookup_bot.command() async def balance_equation(ctx, arg1): EquationBalancer.validate_formula_input(arg1) await ctx.send(lookup_output_container) greenprint("[+] Loaded Discord commands") ################################################################################ # AND NOW WE RUN THE BOT!!! YAY!!! I HAVE MORE DEBUGGING TO DO!!######## from variables_for_reality import TESTING from variables_for_reality import SAVE_BASE64 if TESTING == True: lookup_bot.run(discord_key.discord_bot_token, bot=True) else: try: if __name__ == '__main__': SAVE_BASE64 = True DISPLAY_FROM_BASE64 = False lookup_bot.run(discord_key.discord_bot_token, bot=True) else: print("wat") except: redprint("[-] Error starting program") ################################################################################
def pubchem_lookup_by_name_or_CID(self, compound_id, type_of_data: str): ''' Provide a search term and record type requests can be CAS,CID,IUPAC NAME/SYNONYM outputs in the following order: CID, CAS, SMILES, Formula, Name Stores lookup in database if lookup is valid ''' return_relationships = [] # you get multiple records returned from a pubchem search VERY often # so you have to choose the best one to store, This needs to be # presented as an option to the user,and not programmatically # return_index is the result to return, 0 is the first one return_index = 0 data = ["iupac_name", "cid", "cas"] if type_of_data in data: # different methods are used depending on the type of input # one way if type_of_data == ("iupac_name" or "cas"): try: greenprint("[+] Performing Pubchem Query") lookup_results = pubchem.get_compounds(compound_id, 'name') except Exception: # pubchem.PubChemPyError: redprint( "[-] Error in pubchem_lookup_by_name_or_CID : NAME exception" ) self.user_input_was_wrong("pubchem_lookup_by_name_or_CID") # CID requires another way elif type_of_data == "cid": try: greenprint("[+] Performing Pubchem Query") lookup_results = pubchem.Compound.from_cid(compound_id) except Exception: # pubchem.PubChemPyError: redprint("lookup by NAME/CAS exception - name") self.user_input_was_wrong("pubchem_lookup_by_name_or_CID") # once we have the lookup results, do something if isinstance(lookup_results, list): # and len(lookup_results) > 1 : greenprint("[+] Multiple results returned ") for each in lookup_results: query_appendix = [{'cid' : each.cid ,\ #'cas' : each.cas ,\ 'smiles' : each.isomeric_smiles ,\ 'formula' : each.molecular_formula ,\ 'molweight' : each.molecular_weight ,\ 'charge' : each.charge ,\ 'bond_stereo_count' : each.bond_stereo_count ,\ 'bonds' : each.bonds ,\ 'rotatable_bond_count' : each.rotatable_bond_count ,\ 'multipoles_3d' : each.multipoles_3d ,\ 'mmff94_energy_3d' : each.mmff94_energy_3d ,\ 'mmff94_partial_charges_3d': each.mmff94_partial_charges_3d ,\ 'atom_stereo_count' : each.atom_stereo_count ,\ 'h_bond_acceptor_count' : each.h_bond_acceptor_count ,\ 'feature_selfoverlap_3d' : each.feature_selfoverlap_3d ,\ 'cactvs_fingerprint' : each.cactvs_fingerprint ,\ 'iupac_name' : each.iupac_name ,\ 'description' : self.lookup_description ,\ 'image' : self.image }] return_relationships.append(query_appendix) # Right here we need to find a way to store multiple records # and determine the best record to store as the main entry #compound_to_database() TAKES A LIST!!! First element of first element #[ [this thing here] , [not this one] ] #print(return_relationships[return_index]) Database_functions.compound_to_database( return_relationships[return_index]) # if there was only one result or the user supplied a CID for a single chemical elif isinstance(lookup_results, pubchem.Compound): #\ #or (len(lookup_results) == 1 and isinstance(lookup_results, list)) : greenprint("[+] One Result Returned!") query_appendix = [{'cid' : lookup_results.cid ,\ #'cas' : lookup_results.cas ,\ 'smiles' : lookup_results.isomeric_smiles ,\ 'formula' : lookup_results.molecular_formula ,\ 'molweight' : lookup_results.molecular_weight ,\ 'charge' : lookup_results.charge ,\ 'bond_stereo_count' : each.bond_stereo_count ,\ 'bonds' : each.bonds ,\ 'rotatable_bond_count' : each.rotatable_bond_count ,\ 'multipoles_3d' : each.multipoles_3d ,\ 'mmff94_energy_3d' : each.mmff94_energy_3d ,\ 'mmff94_partial_charges_3d': each.mmff94_partial_charges_3d ,\ 'atom_stereo_count' : each.atom_stereo_count ,\ 'h_bond_acceptor_count' : each.h_bond_acceptor_count ,\ 'feature_selfoverlap_3d' : each.feature_selfoverlap_3d ,\ 'cactvs_fingerprint' : each.cactvs_fingerprint ,\ 'iupac_name' : each.iupac_name ,\ 'description' : self.lookup_description ,\ 'iupac_name' : lookup_results.iupac_name ,\ # Local stuff 'description' : self.lookup_description ,\ 'image' : self.image }] return_relationships.append(query_appendix) #print(query_appendix) Database_functions.compound_to_database( return_relationships[return_index]) else: redprint("PUBCHEM LOOKUP BY CID : ELSE AT THE END") #after storing the lookup to the local database, retrive the local entry #This returns an SQLALchemy object return_query = return_relationships[return_index] query_cid = return_query[0].get('cid') local_query = Compound.query.filter_by(cid=query_cid).first() return local_query
def do_lookup(self, user_input, type_of_input): ''' after validation, the user input is used in Pubchem_lookup.pubchem_lookup_by_name_or_CID() pubchemREST_Description_Request(user_input, type_of_input) Image_lookup() ''' try: internal_lookup = Database_functions.internal_local_database_lookup( user_input, type_of_input) # if internal lookup is false, we do a remote lookup and then store the result if internal_lookup == None or False: redprint("[-] Internal Lookup returned false") self.internal_lookup_bool = False # we grab things in the proper order # description first try: description_lookup = pubchemREST_Description_Request( user_input, type_of_input) except Exception as derp: redprint("[-] Description Lookup Failed") print(derp) self.lookup_description = "Description Lookup Failed" #then image try: #if (SAVE_BASE64 == True) : image_lookup = Image_lookup(user_input ,\ image_as_base64 = True ,\ input_type = type_of_input ,\ temp_file = user_input ) except Exception as derp: redprint("[-] Image Lookup Failed") print(derp) image_lookup = None # no image if image_lookup == None: self.image = "No Image Available" # image as base64 elif (image_lookup != None) and (DISPLAY_FROM_BASE64 == True): self.image = str(image_lookup.image_storage) # image as file elif (image_lookup != None) and (DISPLAY_FROM_BASE64 == False): self.image = image_lookup.image_storage self.image_filename = image_lookup.filename else: redprint("[-] Something wierd happened in do_lookup") # Now pubchem self.lookup_description = description_lookup.parsed_result self.lookup_object = self.pubchem_lookup_by_name_or_CID( user_input, type_of_input) # we return the internal lookup if the entry is already in the DB # for some reason, asking if it's true doesn't work here so we use a NOT instead of an Equals. elif internal_lookup != None or False: greenprint("[+] Internal Lookup returned TRUE") self.internal_lookup_bool = True self.lookup_description = internal_lookup.description self.lookup_object = internal_lookup self.image = internal_lookup.image #redprint("==BEGINNING==return query for DB lookup===========") #greenprint(str(internal_lookup)) #redprint("=====END=====return query for DB lookup===========") # its in dire need of proper exception handling except Exception as derp: redprint( '[-] Something happened in the try/except block for the function do_lookup' ) print(derp)
try: if __name__ == '__main__': if TESTING == True: import time #craft a list of queries to test with test_query_list = [["420","cid"],\ ["methanol","iupac_name"],\ ["phenol","iupac_name"],\ ["methylene chloride","iupac_name"] ,\ ["6623","cid"],\ ["5462309","cid"],\ ["24823","cid"],\ ["water","iupac_name"]] ################################################################### # First we do some lookups to pull data and populate the database #add more tests ################################################################### for each in test_query_list: time.sleep(5) Pubchem_lookup(each[0], each[1]) ################################################################### # then we test the "is it stored locally?" function # doesnt need a timer, not gonna ban myself from my own service ################################################################### for each in test_query_list: Pubchem_lookup(each[0], each[1]) except Exception as derp: print(derp) redprint("[-] Cannot run file for some reason")