def test_petfind_orgname(): # Single word organization should not need slicing org1 = 'BARC' org1_pets, _ = find_pets(pf, org_name=org1) # Casing should not matter org2 = 'barc' org2_pets, _ = find_pets(pf, org_name=org2) # This org will require slicing due to the API not finding the org based on the full name org3 = 'Adopt A Pup Animal Rescue' org3_pets, _ = find_pets(pf, org_name=org3) assert isinstance(org1_pets, DataFrame) assert isinstance(org2_pets, DataFrame) assert isinstance(org3_pets, DataFrame) assert org1_pets.shape == org2_pets.shape
def test_default_coords(): # Originally NaN values for rows with BC as a province/state pets, _ = find_pets(pf, location='Vancouver, BC', distance=100) print(pets[[ 'contact.address.lat', 'contact.address.long', 'contact.address.state' ]]) assert isinstance(pets, DataFrame) assert pets[isnull(pets['contact.address.lat'])].shape[0] == 0
def test_default_image(): # This should have a couple defaults in it but due to the way Petfinder selects the pets, you may get a # different set each time so if you don't see default replacing the NaN and just all links then you may want to # rerun this test again until you see it pets, _ = find_pets(pf, location='Baltimore, MD') print(pets['primary_photo_cropped.small']) assert isinstance(pets, DataFrame) assert pets[isnull(pets['primary_photo_cropped.small'])].shape[0] == 0
def test_petfind_location(): # City, State loc1 = 'Baltimore, MD' loc1_pets, _ = find_pets(pf, location=loc1, distance=25) # Postal Code loc2 = '21250' loc2_pets, _ = find_pets(pf, location=loc2, distance=25) # lat, long loc3 = '39.258, -76.713' loc3_pets, _ = find_pets(pf, location=loc3, distance=25, lat_long=True) assert isinstance(loc1_pets, DataFrame) assert Series(['contact.address.address', 'contact.address.lat', 'contact.address.long']). \ isin(loc1_pets.columns).all() assert isinstance(loc2_pets, DataFrame) assert Series(['contact.address.address', 'contact.address.lat', 'contact.address.long']). \ isin(loc2_pets.columns).all() assert isinstance(loc3_pets, DataFrame) assert Series(['contact.address.address', 'contact.address.lat', 'contact.address.long']). \ isin(loc3_pets.columns).all()
def test_petfind_json_location(): search_json_path = os.path.join( os.path.dirname((os.path.dirname(os.path.abspath(__file__)))), 'tests/search.json') with open(search_json_path, 'r') as fp: search = json.load(fp) pets, _ = find_pets(pf, location=search['location'], distance=25) assert isinstance(search, dict) assert isinstance(pets, DataFrame)
def test_petfind_complex(): pets, _ = find_pets(pf, location='Baltimore, MD', animal_type='dog', breed='beagle', distance=50, name='Bayla', age='young', size='small', gender='female', coat='short') assert isinstance(pets, DataFrame) and pets['name'][0] == 'Bayla'
def test_geocode(): locator = Nominatim(user_agent='myGeocoder') pets, _ = find_pets(pf, animal_type='dog', location='Baltimore, MD', distance=25) pets['contact.address.address'] = pets['contact.address.city'].fillna('') + ', ' + \ pets['contact.address.state'].fillna('') + ', ' + \ pets['contact.address.postcode'].fillna('') unique_addresses = pets['contact.address.address'].unique() location_list = np.array([locator.geocode(x) for x in unique_addresses], dtype=object) lat_long_tup = np.array(location_list[:, 1]) for i in range(len(unique_addresses)): pets.loc[pets['contact.address.address'] == unique_addresses[i], ['contact.address.lat', 'contact.address.long']] = \ lat_long_tup[i][0], lat_long_tup[i][1] print(pets[[ 'contact.address.address', 'contact.address.lat', 'contact.address.long' ]]) assert isinstance(pets, DataFrame)
def test_petfind_goodwith(): pets, _ = find_pets(pf, good_with=['cat', 'dog']) assert all(pets['environment.cats']) and all(pets['environment.dogs'])
def test_petfind(): pets, _ = find_pets(pf) assert isinstance(pets, DataFrame) and pets.shape[0] == MAX_PETS
def find_pets_with_cache(pf: Petfinder, location=None, animal_type=None, breed=None, size=None, gender=None, age=None, color=None, coat=None, org_name=None, distance=None, name=None, good_with=[], house_trained=None, special_needs=None, sort=None): # if cache is empty fill with query if cache.get('default') is None: pets, _ = find_pets(pf, location, animal_type, breed, size, gender, age, color, coat, org_name, distance, name, good_with, house_trained, special_needs, sort) # if 'primary_photo_cropped' in pets.columns: # del pets['primary_photo_cropped'] cache.set('default', pets) else: pets = cache.get('default') # search cache for characteristics if animal_type is not None and pets.shape[0] >= num_results: pets = pets.loc[pets['animal_type'] == animal_type] if breed is not None and pets.shape[0] >= num_results: pets = pets.loc[pets['breeds'] == breed] if size is not None and pets.shape[0] >= num_results: pets = pets.loc[pets['size'] == size] if gender is not None and pets.shape[0] >= num_results: pets = pets.loc[pets['gender'] == gender] if age is not None and pets.shape[0] >= num_results: pets = pets.loc[pets['age'] == age] if color is not None and pets.shape[0] >= num_results: pets = pets.loc[pets['colors'] == color] if coat is not None and pets.shape[0] >= num_results: pets = pets.loc[pets['coat'] == coat] if name is not None and pets.shape[0] >= num_results: pets = pets.loc[pets['name'] == name] # location search if location is not None and pets.shape[0] >= num_results: curr_location = locator.geocode(location) curr_latlong = (curr_location.latitude, curr_location.longitude) # remove results with no latlong pets = pets.loc[(np.isnan(pets['contact.address.lat']) is False) & (np.isnan(pets['contact.address.long']) is False)] # pets = pets.loc[((geodesic(curr_latlong, (pets['contact.address.lat'], # pets['contact.address.long'])).miles) < distance)] # there's probably a better way but this works pets['new'] = 0 for index in pets.index: pets.loc[index, 'new'] = geodesic( curr_latlong, (pets.loc[index, 'contact.address.lat'], pets.loc[index, 'contact.address.long'])).miles pets = pets.loc[pets['new'] < distance] del pets['new'] # if there are not enough results in the cache, run query and cache results if pets.shape[0] < num_results: pets, _ = find_pets(pf, location, animal_type, breed, size, gender, age, color, coat, org_name, distance, name, good_with, house_trained, special_needs, sort) temp = cache.get('default') # if 'primary_photo_cropped' in pets.columns: # del pets['primary_photo_cropped'] if 'primary_photo_cropped' in temp.columns: del temp['primary_photo_cropped'] pets = pets.append(temp, ignore_index=True) pets = pets.drop_duplicates( subset=['animal_type', 'gender', 'age', 'coat', 'name']) cache.set('default', pets) else: # if more results than wanted, drop bottom values until there are proper number of results while pets.shape[0] > num_results: pets.drop(pets.index[num_results]) return pets