diff --git a/README.md b/README.md index 882dfb0..c06253f 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,7 @@ Please refer to our [Places endpoint documentation](https://docs.predicthq.com/r ### Features endpoint -The following example obtain features of events which are active between 2017-12-31 and 2018-01-02, with place_id 4671654. +The following example obtain features of events which are active between 2017-12-31 and 2018-01-02, with place_id 4671654. Requested features: * rank_levels for public_holidays @@ -206,7 +206,48 @@ phq = Client(access_token="abc123") suggested_radius = phq.radius.search(location__origin="45.5051,-122.6750") -print(suggested_radius.radius, suggested_radius.radius_unit, suggested_radius.location.to_dict()) +print(suggested_radius.radius, suggested_radius.radius_unit, suggested_radius.location.model_dump(exclude_none=True)) +``` + +### Serializing search results into a dictionary + +All search results can be serialized into a dictionary using the `.model_dump()` method call. + +To keep `None` values use `.model_dump()` + +To remove `None` values use `.model_dump(exclude_none=True)` + +Examples: + +```Python +from predicthq import Client + +phq = Client(access_token="abc123") + + +for event in phq.events.search(q="Katy Perry", rank_level=[4, 5], category="concerts"): + # Serialize event data into a dictionary and remove None values + print(event.model_dump(exclude_none=True)) +``` + +```Python +from predicthq import Client + +phq = Client(access_token="abc123") + + +for feature in phq.features.obtain_features( + active__gte="2017-12-31", + active__lte="2018-01-02", + location__place_id=["4671654"], + phq_rank_public_holidays=True, + phq_attendance_sports__stats=["count", "median"], + phq_attendance_sports__phq_rank={ + "gt": 50 + } +): + # Serialize feature data into a dictionary and remove None values + print(feature.model_dump(exclude_none=True)) ``` ### Config parameters diff --git a/predicthq/endpoints/v1/features/endpoint.py b/predicthq/endpoints/v1/features/endpoint.py index f9cbfd2..bae59ec 100644 --- a/predicthq/endpoints/v1/features/endpoint.py +++ b/predicthq/endpoints/v1/features/endpoint.py @@ -1,25 +1,27 @@ -import inspect - from predicthq.endpoints.base import UserBaseEndpoint from predicthq.endpoints.decorators import accepts, returns + from .schemas import FeatureResultSet class FeaturesEndpoint(UserBaseEndpoint): - BASE_FEATURE_CRITERIA = {"stats": [["sum", "count"]], "phq_rank": [None]} - FIELDS_TO_MUTATE = frozenset([ - "phq_attendance_", - "phq_viewership_sports", - "phq_impact_severe_weather_", - "phq_spend_" - ]) + FIELDS_TO_MUTATE = frozenset( + [ + "phq_attendance_", + "phq_viewership_", + "phq_impact_", + "phq_spend_", + ] + ) @classmethod def mutate_bool_to_default_for_type(cls, user_request_spec): for key, val in user_request_spec.items(): if any(key.startswith(x) for x in cls.FIELDS_TO_MUTATE): - user_request_spec[key] = [cls.BASE_FEATURE_CRITERIA if isinstance(v, bool) else v for v in val] + user_request_spec[key] = [ + cls.BASE_FEATURE_CRITERIA if isinstance(v, bool) else v for v in val + ] @accepts(query_string=False) @returns(FeatureResultSet) diff --git a/predicthq/endpoints/v1/features/schemas.py b/predicthq/endpoints/v1/features/schemas.py index ad636c9..6bbe42b 100644 --- a/predicthq/endpoints/v1/features/schemas.py +++ b/predicthq/endpoints/v1/features/schemas.py @@ -1,9 +1,7 @@ from datetime import date -from typing import List +from typing import Dict, List, Optional, Union -from typing import Optional - -from pydantic import BaseModel +from pydantic import BaseModel, RootModel from predicthq.endpoints.schemas import ResultSet @@ -26,136 +24,11 @@ class FeatureStat(BaseModel): stats: FeatureStats -class Feature(BaseModel): - class Options: - serialize_when_none = False +class Feature(RootModel): + root: Dict[str, Union[date, FeatureStat, FeatureRankLevel]] - date: date - # Attendance based features - phq_attendance_academic_graduation: Optional[FeatureStat] = None - phq_attendance_academic_social: Optional[FeatureStat] = None - phq_attendance_community: Optional[FeatureStat] = None - phq_attendance_concerts: Optional[FeatureStat] = None - phq_attendance_conferences: Optional[FeatureStat] = None - phq_attendance_expos: Optional[FeatureStat] = None - phq_attendance_festivals: Optional[FeatureStat] = None - phq_attendance_performing_arts: Optional[FeatureStat] = None - phq_attendance_school_holidays: Optional[FeatureStat] = None - phq_attendance_sports: Optional[FeatureStat] = None - # Attendance based feature for accommodation vertical - phq_attendance_community_accommodation: Optional[FeatureStat] = None - phq_attendance_concerts_accommodation: Optional[FeatureStat] = None - phq_attendance_conferences_accommodation: Optional[FeatureStat] = None - phq_attendance_expos_accommodation: Optional[FeatureStat] = None - phq_attendance_festivals_accommodation: Optional[FeatureStat] = None - phq_attendance_performing_arts_accommodation: Optional[FeatureStat] = None - phq_attendance_sports_accommodation: Optional[FeatureStat] = None - # Attendance based feature for hospitality vertical - phq_attendance_community_hospitality: Optional[FeatureStat] = None - phq_attendance_concerts_hospitality: Optional[FeatureStat] = None - phq_attendance_conferences_hospitality: Optional[FeatureStat] = None - phq_attendance_expos_hospitality: Optional[FeatureStat] = None - phq_attendance_festivals_hospitality: Optional[FeatureStat] = None - phq_attendance_performing_arts_hospitality: Optional[FeatureStat] = None - phq_attendance_sports_hospitality: Optional[FeatureStat] = None - # Rank based features - phq_rank_daylight_savings: Optional[FeatureRankLevel] = None - phq_rank_health_warnings: Optional[FeatureRankLevel] = None - phq_rank_observances: Optional[FeatureRankLevel] = None - phq_rank_public_holidays: Optional[FeatureRankLevel] = None - phq_rank_school_holidays: Optional[FeatureRankLevel] = None - phq_rank_politics: Optional[FeatureRankLevel] = None - phq_rank_academic_session: Optional[FeatureRankLevel] = None - phq_rank_academic_exam: Optional[FeatureRankLevel] = None - phq_rank_academic_holiday: Optional[FeatureRankLevel] = None - # Impact based feature criteria - phq_impact_severe_weather_air_quality_retail: Optional[FeatureStat] = None - phq_impact_severe_weather_blizzard_retail: Optional[FeatureStat] = None - phq_impact_severe_weather_cold_wave_retail: Optional[FeatureStat] = None - phq_impact_severe_weather_cold_wave_snow_retail: Optional[FeatureStat] = None - phq_impact_severe_weather_cold_wave_storm_retail: Optional[FeatureStat] = None - phq_impact_severe_weather_dust_retail: Optional[FeatureStat] = None - phq_impact_severe_weather_dust_storm_retail: Optional[FeatureStat] = None - phq_impact_severe_weather_flood_retail: Optional[FeatureStat] = None - phq_impact_severe_weather_heat_wave_retail: Optional[FeatureStat] = None - phq_impact_severe_weather_hurricane_retail: Optional[FeatureStat] = None - phq_impact_severe_weather_thunderstorm_retail: Optional[FeatureStat] = None - phq_impact_severe_weather_tornado_retail: Optional[FeatureStat] = None - phq_impact_severe_weather_tropical_storm_retail: Optional[FeatureStat] = None - # Viewership based features - phq_viewership_sports: Optional[FeatureStat] = None - phq_viewership_sports_american_football: Optional[FeatureStat] = None - phq_viewership_sports_american_football_ncaa_men: Optional[FeatureStat] = None - phq_viewership_sports_american_football_nfl: Optional[FeatureStat] = None - phq_viewership_sports_auto_racing: Optional[FeatureStat] = None - phq_viewership_sports_auto_racing_indy_car: Optional[FeatureStat] = None - phq_viewership_sports_auto_racing_nascar: Optional[FeatureStat] = None - phq_viewership_sports_baseball: Optional[FeatureStat] = None - phq_viewership_sports_baseball_mlb: Optional[FeatureStat] = None - phq_viewership_sports_baseball_ncaa_men: Optional[FeatureStat] = None - phq_viewership_sports_basketball: Optional[FeatureStat] = None - phq_viewership_sports_basketball_ncaa_women: Optional[FeatureStat] = None - phq_viewership_sports_basketball_ncaa_men: Optional[FeatureStat] = None - phq_viewership_sports_basketball_nba: Optional[FeatureStat] = None - phq_viewership_sports_boxing: Optional[FeatureStat] = None - phq_viewership_sports_golf: Optional[FeatureStat] = None - phq_viewership_sports_golf_masters: Optional[FeatureStat] = None - phq_viewership_sports_golf_pga_championship: Optional[FeatureStat] = None - phq_viewership_sports_golf_pga_tour: Optional[FeatureStat] = None - phq_viewership_sports_golf_us_open: Optional[FeatureStat] = None - phq_viewership_sports_horse_racing: Optional[FeatureStat] = None - phq_viewership_sports_horse_racing_belmont_stakes: Optional[FeatureStat] = None - phq_viewership_sports_horse_racing_kentucky_derby: Optional[FeatureStat] = None - phq_viewership_sports_horse_racing_preakness_stakes: Optional[FeatureStat] = None - phq_viewership_sports_ice_hockey: Optional[FeatureStat] = None - phq_viewership_sports_ice_hockey_nhl: Optional[FeatureStat] = None - phq_viewership_sports_mma: Optional[FeatureStat] = None - phq_viewership_sports_mma_ufc: Optional[FeatureStat] = None - phq_viewership_sports_soccer: Optional[FeatureStat] = None - phq_viewership_sports_soccer_concacaf_champions_league: Optional[FeatureStat] = None - phq_viewership_sports_soccer_concacaf_gold_cup: Optional[FeatureStat] = None - phq_viewership_sports_soccer_copa_america_men: Optional[FeatureStat] = None - phq_viewership_sports_soccer_fifa_world_cup_women: Optional[FeatureStat] = None - phq_viewership_sports_soccer_fifa_world_cup_men: Optional[FeatureStat] = None - phq_viewership_sports_soccer_mls: Optional[FeatureStat] = None - phq_viewership_sports_soccer_uefa_champions_league_men: Optional[FeatureStat] = None - phq_viewership_sports_softball: Optional[FeatureStat] = None - phq_viewership_sports_softball_ncaa_women: Optional[FeatureStat] = None - phq_viewership_sports_tennis: Optional[FeatureStat] = None - phq_viewership_sports_tennis_us_open: Optional[FeatureStat] = None - phq_viewership_sports_tennis_wimbledon: Optional[FeatureStat] = None - # PHQ spend based feature - phq_spend_conferences: Optional[FeatureStat] = None - phq_spend_expos: Optional[FeatureStat] = None - phq_spend_sports: Optional[FeatureStat] = None - phq_spend_community: Optional[FeatureStat] = None - phq_spend_concerts: Optional[FeatureStat] = None - phq_spend_festivals: Optional[FeatureStat] = None - phq_spend_performing_arts: Optional[FeatureStat] = None - # PHQ spend accommodation based feature - phq_spend_conferences_accommodation: Optional[FeatureStat] = None - phq_spend_expos_accommodation: Optional[FeatureStat] = None - phq_spend_sports_accommodation: Optional[FeatureStat] = None - phq_spend_community_accommodation: Optional[FeatureStat] = None - phq_spend_concerts_accommodation: Optional[FeatureStat] = None - phq_spend_festivals_accommodation: Optional[FeatureStat] = None - phq_spend_performing_arts_accommodation: Optional[FeatureStat] = None - # PHQ spend hospitality based feature - phq_spend_conferences_hospitality: Optional[FeatureStat] = None - phq_spend_expos_hospitality: Optional[FeatureStat] = None - phq_spend_sports_hospitality: Optional[FeatureStat] = None - phq_spend_community_hospitality: Optional[FeatureStat] = None - phq_spend_concerts_hospitality: Optional[FeatureStat] = None - phq_spend_festivals_hospitality: Optional[FeatureStat] = None - phq_spend_performing_arts_hospitality: Optional[FeatureStat] = None - # PHQ spend transportation based feature - phq_spend_conferences_transportation: Optional[FeatureStat] = None - phq_spend_expos_transportation: Optional[FeatureStat] = None - phq_spend_sports_transportation: Optional[FeatureStat] = None - phq_spend_community_transportation: Optional[FeatureStat] = None - phq_spend_concerts_transportation: Optional[FeatureStat] = None - phq_spend_festivals_transportation: Optional[FeatureStat] = None - phq_spend_performing_arts_transportation: Optional[FeatureStat] = None + def __getattr__(self, name: str) -> Union[date, FeatureStat, FeatureRankLevel]: + return self.root[name] class FeatureResultSet(ResultSet): diff --git a/predicthq/version.py b/predicthq/version.py index 903a158..dcbfb52 100644 --- a/predicthq/version.py +++ b/predicthq/version.py @@ -1 +1 @@ -__version__ = "3.4.0" +__version__ = "3.5.0"