Skip to content

Commit

Permalink
Merge pull request #122 from EricNeville/facilities-filtering
Browse files Browse the repository at this point in the history
Facilities filtering
  • Loading branch information
AnthonyBloomer authored Apr 5, 2021
2 parents bf730db + e5c9dea commit 7fcd27b
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 2 deletions.
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,29 @@ dublin_map.add_colorbar()
dublin_map.save("ireland_rent.html")
print("Done, please checkout the html file")
```

Search for apartments for rent in Dublin with an alarm and parking.

```python
from daftlistings import Daft, Location, SearchType, PropertyType, Facility

daft = Daft()
daft.set_location(Location.DUBLIN)
daft.set_search_type(SearchType.RESIDENTIAL_RENT)
daft.set_property_type(PropertyType.APARTMENT)
daft.set_facility(Facility.PARKING)
daft.set_facility(Facility.ALARM)

listings = daft.search()

for listing in listings:
print(listing.title)
print(listing.abbreviated_price)
print(listing.daft_link)
print()
```


## Contributing

- Fork the project and clone locally.
Expand Down
27 changes: 27 additions & 0 deletions daftlistings/daft.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,16 @@ def _add_filter(self, name: str, value: str):
self._filters.append({"name": name,
"values": [value]})

def _add_and_filter(self, name: str, value: str):
if self._andFilters:
for f in self._andFilters:
if f["name"] == name:
if value not in f["values"]:
f["values"].append(value)
return
self._andFilters.append({"name": name,
"values": [value]})

def _add_sort_filter(self, sort_filter: str):
self._sort_filter = sort_filter

Expand Down Expand Up @@ -153,6 +163,21 @@ def set_location(self, location: Union[Location, str]):
else:
raise TypeError("Argument must be location.Location or string.")

def set_facility(self, facility: Facility):
if self._section == None:
raise ValueError('SearchType must be set before Facility')
else:
if isinstance(facility, Facility):
if self._section in [s.value for s in facility.valid_types]:
self._add_and_filter('facilities', facility.value)
else:
search_type = [(name,member) for name, member in SearchType.__members__.items() if member.value == self._section][0]
compatible_facilities = [f.name for f in Facility if search_type[1] in f.valid_types]
raise ValueError(f"Facility {facility.name} incompatible with SearchType {search_type[0]}\nThe following facilities are compatible with this SearchType:\n{compatible_facilities}")
else:
raise TypeError("Argument must be of type Facility")


def set_sort_type(self, sort_type: SortType):
if isinstance(sort_type, SortType):
self._add_sort_filter(sort_type.value)
Expand All @@ -178,6 +203,8 @@ def _make_payload(self) -> Dict:
payload["section"] = self._section
if self._filters:
payload["filters"] = self._filters
if self._andFilters:
payload["andFilters"] = self._andFilters
if self._ranges:
payload["ranges"] = self._ranges
if self._geoFilter:
Expand Down
36 changes: 36 additions & 0 deletions daftlistings/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,42 @@ class MiscFilter(enum.Enum):
TOILETS = "toilets"


class Facility(enum.Enum):
def __new__(cls, *args, **kwargs):
obj = object.__new__(cls)
obj._value_ = args[0]
return obj

def __init__(self, _, valid_types):
self.valid_types = valid_types

ALARM = ("alarm", [SearchType.RESIDENTIAL_SALE, SearchType.RESIDENTIAL_RENT, SearchType.COMMERCIAL_SALE, SearchType.COMMERCIAL_RENT, SearchType.SHARING, SearchType.STUDENT_ACCOMMODATION])
CENTRAL_HEATING_GAS = ("gas-fired-central-heating", [SearchType.RESIDENTIAL_SALE])
CENTRAL_HEATING_OIL = ("oil-fired-central-heating", [SearchType.RESIDENTIAL_SALE])
PARKING = ("parking", [SearchType.RESIDENTIAL_SALE, SearchType.RESIDENTIAL_RENT, SearchType.COMMERCIAL_SALE, SearchType.COMMERCIAL_RENT, SearchType.SHARING, SearchType.STUDENT_ACCOMMODATION])
WHEELCHAIR_ACCESS = ("wheelchair-access", [SearchType.RESIDENTIAL_SALE, SearchType.RESIDENTIAL_RENT, SearchType.SHARING, SearchType.STUDENT_ACCOMMODATION])
WIRED_FOR_CABLE_TELEVISION = ("wired-for-cable-television", [SearchType.RESIDENTIAL_SALE])
CABLE_TELEVISION = ("cable-television", [SearchType.RESIDENTIAL_RENT, SearchType.SHARING, SearchType.STUDENT_ACCOMMODATION])
DISHWASHER = ("dishwasher", [SearchType.RESIDENTIAL_RENT, SearchType.SHARING, SearchType.STUDENT_ACCOMMODATION])
GARDEN_PATIO_BALCONY = ("garden-patio-balcony", [SearchType.RESIDENTIAL_RENT, SearchType.SHARING, SearchType.STUDENT_ACCOMMODATION])
CENTRAL_HEATING = ("central-heating", [SearchType.RESIDENTIAL_RENT, SearchType.SHARING, SearchType.STUDENT_ACCOMMODATION])
INTERNET = ("internet", [SearchType.RESIDENTIAL_RENT, SearchType.SHARING, SearchType.STUDENT_ACCOMMODATION])
MICROWAVE = ("microwave", [SearchType.RESIDENTIAL_RENT, SearchType.SHARING, SearchType.STUDENT_ACCOMMODATION])
PETS_ALLOWED = ("pets-allowed", [SearchType.RESIDENTIAL_RENT, SearchType.SHARING, SearchType.STUDENT_ACCOMMODATION])
SMOKING = ("smoking", [SearchType.RESIDENTIAL_RENT, SearchType.SHARING, SearchType.STUDENT_ACCOMMODATION])
SERVICED_PROPERTY = ("serviced-property", [SearchType.RESIDENTIAL_RENT, SearchType.SHARING, SearchType.STUDENT_ACCOMMODATION])
DRYER = ("dryer", [SearchType.RESIDENTIAL_RENT, SearchType.SHARING, SearchType.STUDENT_ACCOMMODATION])
WASHING_MACHINE = ("washing-machine", [SearchType.RESIDENTIAL_RENT, SearchType.SHARING, SearchType.STUDENT_ACCOMMODATION])
ENSUITE = ("ensuite", [SearchType.SHARING, SearchType.STUDENT_ACCOMMODATION])
CAT_5_CABLING = ("cat-5-cabling", [SearchType.COMMERCIAL_SALE, SearchType.COMMERCIAL_RENT])
CAT_6_CABLING = ("cat-6-data-cabling", [SearchType.COMMERCIAL_SALE, SearchType.COMMERCIAL_RENT])
KITCHEN_AREA = ("kitchen-area", [SearchType.COMMERCIAL_SALE, SearchType.COMMERCIAL_RENT])
MEETING_ROOMS = ("meeting-rooms", [SearchType.COMMERCIAL_SALE, SearchType.COMMERCIAL_RENT])
RECEPTION = ("reception", [SearchType.COMMERCIAL_SALE, SearchType.COMMERCIAL_RENT])
PHONE_LINES = ("phone-lines", [SearchType.COMMERCIAL_SALE, SearchType.COMMERCIAL_RENT])
TOILETS = ("toilets", [SearchType.COMMERCIAL_SALE, SearchType.COMMERCIAL_RENT])


class AddedSince(enum.Enum):
DAYS_3 = "now-3d/d"
DAYS_7 = "now-7d/d"
Expand Down
16 changes: 16 additions & 0 deletions examples/facilities.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from daftlistings import Daft, Location, SearchType, PropertyType, Facility

daft = Daft()
daft.set_location(Location.DUBLIN)
daft.set_search_type(SearchType.RESIDENTIAL_RENT)
daft.set_property_type(PropertyType.APARTMENT)
daft.set_facility(Facility.PARKING)
daft.set_facility(Facility.ALARM)

listings = daft.search()

for listing in listings:
print(listing.title)
print(listing.abbreviated_price)
print(listing.daft_link)
print()
7 changes: 5 additions & 2 deletions tests/test_daft_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
Listing,
AddedSince,
PropertyType,
Facility
)


Expand All @@ -18,7 +19,8 @@ class DaftTest(unittest.TestCase):
def test_search(self, mock_post):
url = "https://search-gateway.dsch.ie/v1/listings"
payload = {
"section": "new-homes",
"section": "residential-for-sale",
"andFilters": [{"name":"facilities", "values": ["alarm"]}],
"ranges": [
{"name": "salePrice", "from": "250000", "to": "300000"},
{"name": "numBeds", "from": "3", "to": "3"},
Expand All @@ -38,7 +40,7 @@ def test_search(self, mock_post):

daft = Daft()

daft.set_search_type(SearchType.NEW_HOMES)
daft.set_search_type(SearchType.RESIDENTIAL_SALE)
daft.set_location(Location.KILDARE)
daft.set_location("Kildare")
daft.set_sort_type(SortType.PRICE_ASC)
Expand All @@ -51,6 +53,7 @@ def test_search(self, mock_post):
daft.set_max_floor_size(1000)
daft.set_min_floor_size(1000)
daft.set_added_since(AddedSince.DAYS_14)
daft.set_facility(Facility.ALARM)
daft.search()

mock_post.assert_called_with(url, headers=headers, json=payload)
Expand Down

0 comments on commit 7fcd27b

Please sign in to comment.