class Name(Decodable): def __init__( self, first_name: str, other_name: str, last_name: str ) -> None: self._first_name = first_name self._other_name = other_name self._last_name = last_name return first = Immutable(lambda s: s._first_name) other = Immutable(lambda s: s._other_name) last = Immutable(lambda s: s._last_name) @classmethod def decode(cls: Type[T], data: Any) -> T: return cls( first_name=data['first_name'], other_name=data['other_name'], last_name=data['last_name'] )
class Position(Decodable): def __init__(self, indexid: int, name: str, categories: List[PositionCategory]) -> None: self._indexid = indexid self._name = name self._categories = categories return name = Immutable(lambda s: s._name) categories = Immutable(lambda s: s._categories) lowercase_name = Immutable(lambda s: s._name.lower()) sole_category = Immutable(lambda s: s._categories[0] if len(s._categories) == 1 else None) @classmethod def decode(cls: Type[T], data: Any) -> T: return cls(indexid=data['indexid'], name=data['name'], categories=PositionCategory.optionally_decode_many( data['categories'], default_to_empty_list=True)) def __eq__(self, other) -> bool: if not isinstance(other, Position): return False if self._indexid == other._indexid: return True return False def __ne__(self, other) -> bool: return not other == self
class Round(Decodable): """Points attributed to a player in a particular round""" def __init__(self, sequence: int, scores: List[Score]) -> None: self._round_sequence = sequence self._scores = scores return round_sequence = Immutable(lambda s: s._round_sequence) scores = Immutable(lambda s: s._scores) total_points = Immutable(lambda s: sum([k.value for k in s._scores])) def score_for_metric(self, metric: FantasyMetric) -> Optional[int]: for score in self._scores: if score.fantasy_metric == metric: return score.value continue return None @classmethod def decode(cls: Type[T], data: Any) -> T: return cls(sequence=data['round_sequence'], scores=Score.decode_many(data['scores']))
class Team: def __init__(self, name: str) -> None: self._name = name return name = Immutable(lambda s: s._name) lowercase_name = Immutable(lambda s: s._name.lower())
class League(Decodable): _PATH = '/league' def __init__(self, public_id: str, teams: List[TeamSummary], commissioner_id: str, name: str, created: NozomiTime) -> None: self._public_id = public_id self._teams = teams self._commissioner_id = commissioner_id self._name = name self._created = created return name = Immutable(lambda s: s._name) public_id = Immutable(lambda s: s._public_id) teams = Immutable(lambda s: s._teams) def is_commissioned_by(self, human: Human) -> bool: """Return True if the supplied human is the league commissioner""" return human.public_id == self._commissioner_id @classmethod def retrieve(cls: Type[T], public_id: str, credentials: RequestCredentials, configuration: Configuration) -> Optional[T]: """ Optionally return a League with the given public ID, if it exists """ assert isinstance(public_id, str) parameters = URLParameters([ URLParameter('league', public_id), URLParameter('season', '2020') # MVP hardcode ]) request = ApiRequest(path=cls._PATH, method=HTTPMethod.GET, configuration=configuration, data=None, url_parameters=parameters, credentials=credentials) return cls.optionally_decode(request.response_data) @classmethod def decode(cls: Type[T], data: Any) -> T: return cls(public_id=data['public_id'], teams=TeamSummary.decode_many(data['teams']), commissioner_id=data['commissioner_id'], name=data['name'], created=NozomiTime.decode(data['created']))
class PositionRequirement(Decodable): def __init__(self, count: int, position_name: str) -> None: self._count = count self._position_name = position_name return count: int = Immutable(lambda s: s._count) position_name: str = Immutable(lambda s: s._position_name) @classmethod def decode(cls: Type[T], data: Any) -> T: return cls(count=data['count'], position_name=data['position_name'])
class Price(Decodable): def __init__(self, magnitude: Decimal, denomination: Denomination) -> None: self._magnitude = magnitude self._denomination = denomination return magnitude = Immutable(lambda s: s._magnitude) denomination = Immutable(lambda s: s._denomination) @classmethod def decode(cls: Type[T], data: Any) -> T: return cls(magnitude=Decimal(data['magnitude']), denomination=Denomination.decode(data['denomination']))
class PositionCategory(Decodable): def __init__( self, indexid: int, name: str ) -> None: self._indexid = indexid self._name = name return name = Immutable(lambda s: s._name) @classmethod def decode(cls: Type[T], data: Any) -> T: return cls( indexid=data['indexid'], name=data['name'] ) def __eq__(self, other) -> bool: if not isinstance(other, PositionCategory): return False if self._indexid == other._indexid: return True return False def __ne__(self, other) -> bool: return not other == self
class Human(Decodable): _PATH = '/human' def __init__(self, public_id: str, email: CommunicationMethod, handle: str) -> None: self._email = email self._public_id = public_id self._handle = handle return display_name: str = Immutable( lambda s: s._handle if s._handle else s._email.body.split('@')[0]) public_id: str = Immutable(lambda s: s._public_id) email: CommunicationMethod = Immutable(lambda s: s._email) handle: str = Immutable(lambda s: s._handle) @classmethod def retrieve(cls: Type[T], public_id: str, credentials: RequestCredentials, configuration: Configuration) -> Optional[T]: """ Optionally return a Human with the given public ID, if it exists """ assert isinstance(public_id, str) target = URLParameter('public_id', public_id) parameters = URLParameters([target]) request = ApiRequest(path=cls._PATH, method=HTTPMethod.GET, configuration=configuration, data=None, url_parameters=parameters, credentials=credentials) return cls.optionally_decode(request.response_data) @classmethod def decode(cls: Type[T], data: Any) -> T: return cls(public_id=data['public_id'], email=CommunicationMethod.decode(data['email']), handle=data['handle'])
class Profile(Decodable): def __init__(self, first_name: str, last_name: str, position: Optional[Position], public_id: str, team_name: str) -> None: self._first_name = first_name self._last_name = last_name self._position = position self._public_id = public_id self._team_name = team_name return first_name = Immutable(lambda s: s._first_name) last_name = Immutable(lambda s: s._last_name) public_id = Immutable(lambda s: s._public_id) position = Immutable(lambda s: s._position) position_name = Immutable(lambda s: s._position.name if s._position else None) team_name = Immutable(lambda s: s._team_name) full_name = Immutable(lambda s: s._first_name + ' ' + s._last_name) @classmethod def decode(cls: Type[T], data: Any) -> T: return cls(first_name=data['first_name'], last_name=data['last_name'], position=Position.optionally_decode(data['position']), public_id=data['public_id'], team_name=data['team_name'])
class Score(Decodable): """An integer score with respect to some fantasy metric""" def __init__(self, fantasy_metric: FantasyMetric, score: int) -> None: self._fantasy_metric = fantasy_metric self._score = score return value = Immutable(lambda s: s._score) fantasy_metric = Immutable(lambda s: s._fantasy_metric) fantasy_metric_name = Immutable(lambda s: s._fantasy_metric.value) @classmethod def decode(cls: Type[T], data: Any) -> T: return cls(fantasy_metric=FantasyMetric.decode( data['fantasy_metric_name']), score=data['score'])
class Denomination(Decodable): def __init__(self, name: str, iso_4217: str, symbol: str) -> None: self._name = name self._iso_4217 = iso_4217 self._symbol = symbol return name: str = Immutable(lambda s: s._name) iso_4217: str = Immutable(lambda s: s._iso_4217) symbol: str = Immutable(lambda s: s._symbol) @classmethod def decode(cls: Type[T], data: Any) -> T: return cls(name=data['name'], iso_4217=data['iso_4217'], symbol=data['symbol'])
class Composition(Decodable): def __init__(self, position_requirements: List[PositionRequirement], category_requirements: List[CategoryRequirement]) -> None: self._position_requirements = position_requirements self._category_requirements = category_requirements return position_requirements = Immutable(lambda s: s._position_requirements) category_requirements = Immutable(lambda s: s._category_requirements) unique_positions: List[str] = Immutable( lambda s: list(set(r.position for r in s._position_requirements))) @classmethod def decode(cls: Type[T], data: Any) -> T: return cls(position_requirements=PositionRequirement.decode_many( data['position_requirements']), category_requirements=CategoryRequirement.decode_many( data['category_requirements']))
class CommunicationMethod(Decodable): def __init__(self, public_id: str, mode: int, body: str, confirmed: bool) -> None: self._public_id = public_id self._mode = mode self._body = body self._confirmed = confirmed return body = Immutable(lambda s: s._body) public_id = Immutable(lambda s: s._public_id) confirmed = Immutable(lambda s: s._confirmed) @classmethod def decode(cls: Type[T], data: Any) -> T: return cls(public_id=data['public_id'], mode=data['mode'], body=data['body'], confirmed=data['confirmed'])
class Offer(Decodable): _PATH = '/offer' def __init__(self, public_id: str, name: str, prices: List[Price], products: List[Product], frequency: Frequency) -> None: self._public_id = public_id self._name = name self._prices = prices self._products = products self._frequency = frequency return public_id: str = Immutable(lambda s: s._public_id) name: str = Immutable(lambda s: s._name) prices: List[Price] = Immutable(lambda s: s._prices) products: List[Product] = Immutable(lambda s: s._products) features: List[str] = Immutable(lambda s: s._flatten_features()) frequency: Frequency = Immutable(lambda s: s._frequency) price_map: Dict[str, Decimal] = Immutable( lambda s: {p.denomination.iso_4217: str(p.magnitude) for p in s._prices}) def _flatten_features(self) -> List[str]: flat_features: List[str] = list() for product in self._products: for feature in product.features: flat_features.append(feature) return flat_features @classmethod def decode(cls: Type[T], data: Any) -> T: return cls(public_id=data['public_id'], name=data['name'], prices=Price.decode_many(data['prices']), products=Product.decode_many(data['products']), frequency=Frequency(data['frequency'])) @classmethod def retrieve(cls: Type[T], public_id: str, credentials: RequestCredentials, configuration: Configuration) -> Optional[T]: parameters = URLParameters([URLParameter('offer', public_id)]) request = ApiRequest(path=cls._PATH, method=HTTPMethod.GET, configuration=configuration, data=None, url_parameters=parameters, credentials=credentials) return cls.optionally_decode(request.response_data)
class Challenge(Decodable): _PATH = '/communication-method/challenge' def __init__(self, expiration: NozomiTime, completed: Optional[NozomiTime], is_expired: bool, method_id: str) -> None: self._expiration = expiration self._is_expired = is_expired self._completed = completed self._method_id = method_id return is_completed: bool = Immutable(lambda s: s._completed is not None) is_expired: bool = Immutable(lambda s: s._is_expired) method_id: str = Immutable(lambda s: s._method_id) @classmethod def decode(cls: Type[T], data: Any) -> T: return cls(expiration=NozomiTime.decode(data['expiration']), completed=NozomiTime.optionally_decode(data['completed']), is_expired=data['is_expired'], method_id=data['method_id']) @classmethod def retrieve(cls: Type[T], code: str, credentials: RequestCredentials, configuration: Configuration) -> Optional[T]: parameters = URLParameters([URLParameter('code', code)]) request = ApiRequest(path=cls._PATH, method=HTTPMethod.GET, configuration=configuration, data=None, url_parameters=parameters, credentials=credentials) return cls.optionally_decode(request.response_data)
class TeamSummary(Decodable): def __init__(self, manager_id: str, manager_name: str, team_name: str, league_id: str) -> None: self._manager_id = manager_id self._manager_name = manager_name self._team_name = team_name self._league_id = league_id return manager_id = Immutable(lambda s: s._manager_id) manager_name = Immutable(lambda s: s._manager_name) team_name = Immutable(lambda s: s._team_name) league_id = Immutable(lambda s: s._league_id) @classmethod def decode(cls: Type[T], data: Any) -> T: return cls(manager_id=data['manager_public_id'], manager_name=data['manager_name'], league_id=data['league_public_id'], team_name=data['team_name'])
class CategoryRequirement(Decodable): def __init__( self, count: int, category: PositionCategory ) -> None: self._count = count self._category = category return count: int = Immutable(lambda s: s._count) category: PositionCategory = Immutable(lambda s: s._category) @classmethod def decode(cls: Type[T], data: Any) -> T: return cls( count=data['count'], category=PositionCategory.decode(data['category']) )
class FilledComposition: """ A utility class coralling Composition and Player data into a combined unit. Useful on the client side for presentation purposes. There is no equivalent object in the Draft Sport API """ def __init__(self, requirements: List[FilledRequirement]) -> None: self._requirements = requirements return requirements: List[FilledRequirement] = Immutable( lambda s: s._requirements)
class Product(Decodable): def __init__(self, public_id: str, name: str, features: List[str]) -> None: self._public_id = public_id self._name = name self._features = features return features = Immutable(lambda s: s._features) @classmethod def decode(cls: Type[T], data: Any) -> T: return cls(public_id=data['public_id'], name=data['name'], features=data['features'])
class SecretResetRequest(Decodable): _PATH = '/human/secret-reset-request' def __init__(self, created: NozomiTime) -> None: self._created = created return created = Immutable(lambda s: s._created) @classmethod def decode(cls: Type[T], data: Any) -> None: return cls(created=NozomiTime.decode(data['created'])) @classmethod def create(cls: Type[T], email_address: str, configuration: Configuration) -> T: target = URLParameter('email', email_address) parameters = URLParameters([target]) request = ApiRequest(path=cls._PATH, method=HTTPMethod.POST, configuration=configuration, url_parameters=parameters) return cls.decode(request.response_data) @classmethod def retrieve(cls: Type[T], reset_key: str, configuration: Configuration) -> Optional[T]: target = URLParameter('reset-key', reset_key) parameters = URLParameters([target]) request = ApiRequest(path=cls._PATH, method=HTTPMethod.GET, configuration=configuration, url_parameters=parameters) return cls.optionally_decode(request.response_data)
class Pick(Decodable): def __init__(self, created: NozomiTime, manager_id: str, profile: Profile, league_id: str, as_at: NozomiTime) -> None: self._created = created self._manager_id = manager_id self._profile = profile self._league_id = league_id self._as_at = as_at return profile = Immutable(lambda s: s._profile) @classmethod def decode(cls: Type[T], data: Any) -> T: return cls(created=NozomiTime.decode(data['created']), manager_id=data['manager_id'], profile=Profile.decode(data['player']), league_id=data['league_id'], as_at=NozomiTime.decode(data['as_at']))
class Points(Decodable): def __init__(self, average_points: int, total_points: int, points_last_round: int, points_per_minute_played: int, rounds: List[Round]) -> None: self._average_points = average_points self._total_points = total_points self._points_last_round = points_last_round self._points_per_minute_played = points_per_minute_played self._rounds = sorted(rounds, key=lambda r: r.round_sequence) self._cached_flattened_rounds: Optional[Dict[str, List[int]]] = None return average_points = Immutable(lambda s: s._average_points) total_points = Immutable(lambda s: s._total_points) points_last_round = Immutable(lambda s: s._points_last_round) points_per_minute_played = Immutable(lambda s: s._points_per_minute_played) rounds = Immutable(lambda s: s._rounds) normalised_rounds = Immutable(lambda s: s._compute_normalised_rounds()) flattened_rounds = Immutable(lambda s: s._retrieved_flattened_rounds()) _all_metric_keys = Immutable(lambda s: s._compute_all_metric_keys()) def score_for_metric(self, metric: FantasyMetric, in_round: Union[int, SemanticRound]) -> Optional[int]: if len(self._rounds) < 0: return None def compute_index(intention: Union[int, SemanticRound]) -> int: if isinstance(intention, SemanticRound): if intention == SemanticRound.LATEST: return -1 if intention == SemanticRound.FIRST: return 0 pass assert isinstance(intention, int) return intention rounds = sorted(self.rounds, key=lambda r: r.round_sequence) index = compute_index(in_round) if len(rounds) - 1 < index: return None target_round = rounds[index] return target_round.score_for_metric(metric) def _compute_all_metric_keys(self) -> List[str]: keys: Set[str] = set() for rou in self._rounds: for score in rou.scores: keys.add(score.fantasy_metric_name) return sorted(keys) @classmethod def decode(cls: Type[T], data: Any) -> T: return cls(points_per_minute_played=data['points_per_minute_played'], average_points=data['average_points'], total_points=data['total_points'], points_last_round=data['points_last_round'], rounds=Round.decode_many(data['rounds'])) def _compute_normalised_rounds(self) -> List[Round]: all_keys = self._all_metric_keys def _scores_for_round(rou: Round) -> List[Score]: scores: List[Score] = list() for key in all_keys: found = False for score in rou.scores: if score.fantasy_metric_name == key: scores.append(score) found = True break if found is True: break scores.append( Score(fantasy_metric=FantasyMetric.decode(key), score=0)) return sorted(scores, key=lambda s: s.fantasy_metric_name) rounds: List[Round] = list() for rou in self._rounds: rounds.append( Round(sequence=rou.round_sequence, scores=_scores_for_round(rou))) return sorted(rounds, key=lambda r: r.round_sequence) def _retrieved_flattened_rounds(self) -> Dict[str, List[int]]: if self._cached_flattened_rounds is None: self._cached_flattened_rounds = self._compute_flattened_rounds() return self._cached_flattened_rounds def _compute_flattened_rounds(self) -> Dict[str, List[int]]: flat_rounds: Dict[str, List[int]] = dict() for key in self._all_metric_keys: metric_stats: List[int] = list() for rou in self._rounds: found = False for score in rou.scores: if score.fantasy_metric_name == key: metric_stats.append(score.value) found = True break continue if found is True: continue metric_stats.append(0) continue flat_rounds[key] = metric_stats continue return flat_rounds
class FilledRequirement: """ Utility class coralling Requirement & Player data. Useful for client presentation purposes. There is no equivalent object in the Draft Sport API """ def __init__(self, requirement: Requirement, picks: List[Pick]) -> None: self._picks = picks self._requirement = requirement return picks = Immutable(lambda s: s._picks) name = Immutable(lambda s: s._compute_requirement_name()) position_name = Immutable(lambda s: s._requirement.position_name) count = Immutable(lambda s: s._requirement.count) is_position: bool = Immutable( lambda s: isinstance(s._requirement, PositionRequirement)) is_category: bool = Immutable( lambda s: isinstance(s._requirement, CategoryRequirement)) is_plural: bool = Immutable(lambda s: s.count > 1) number_filled: int = Immutable(lambda s: len(s.picks)) empty: bool = Immutable(lambda s: len(s.picks) < 1) satisfied: bool = Immutable(lambda s: len(s.picks) == s.count) not_satisfied: bool = Immutable(lambda s: not s.satisfied) def _compute_requirement_name(self) -> str: if isinstance(self._requirement, CategoryRequirement): name = self._requirement.category.name return name[0].upper() + name[1:].lower() if isinstance(self._requirement, PositionRequirement): return self._requirement.position_name raise TypeError
class ScoreCard(Decodable, Encodable): _PATH = '/fantasy/score-card' _LIST_PATH = '/fantasy/score-card/list' def __init__(self, profile: Profile, season_id: str, limit: int, offset: int, query_count: int, sequence: int, requesting_agent_id: str, points: Points, query_time: int) -> None: self._profile = profile self._season_id = season_id self._limit = limit self._offset = offset self._query_count = query_count self._sequence = sequence self._requesting_agent_id = requesting_agent_id self._points = points self._query_time = query_time return public_id = Immutable(lambda s: s._profile.public_id) profile = Immutable(lambda s: s._profile) season_id = Immutable(lambda s: s._season_id) limit = Immutable(lambda s: s._limit) offset = Immutable(lambda s: s._offset) query_count = Immutable(lambda s: s._query_count) sequence = Immutable(lambda s: s._sequence) requesting_agent_id = Immutable(lambda s: s._requesting_agent_id) points = Immutable(lambda s: s._points) query_time = Immutable(lambda s: s._query_time) query_time_seconds = Immutable(lambda s: str(int(s._query_time) / 1000000)) def has_position_with_name(self, name: str) -> bool: """Return True if this Player has the named position""" return self._profile.position_name == name def has_position_in_category(self, category: PositionCategory) -> bool: """Return True if this Player has a position in the supplied category""" return category in self._profile.position.categories def encode(self) -> Dict[str, Any]: return { 'player': self._profile.encode(), 'limit': self._limit, 'offset': self._offset, 'sequence': self._sequence, 'requesting_agent_id': self._requesting_agent_id, 'points': self._points.encode(), 'query_time': self._query_time, 'query_count': self._query_coun } @classmethod def decode(cls: Type[T], data: Any) -> T: return cls(profile=Profile.decode(data['player']), season_id=data['fantasy_season_id'], limit=data['limit'], offset=data['offset'], query_count=data['query_count'], sequence=data['sequence'], requesting_agent_id=data['requesting_agent_id'], points=Points.decode(data['points']), query_time=data['query_time']) @classmethod def retrieve(cls: Type[T], public_id: str, season: Season, credentials: Optional[RequestCredentials], configuration: Optional[Configuration]) -> Optional[T]: parameters = URLParameters([ URLParameter('public_id', public_id), URLParameter('season', season.public_id) ]) request = ApiRequest(path=cls._PATH, method=HTTPMethod.GET, data=None, url_parameters=parameters, credentials=credentials, configuration=configuration) return cls.optionally_decode(request.response_data) @classmethod def retrieve_many( cls: Type[T], season: Season, offset: int, limit: int, configuration: Configuration, order_by: OrderBy = OrderBy.TOTAL_SEASON_POINTS, order: Order = Order.DESCENDING, name_fragment: Optional[str] = None, credentials: Optional[RequestCredentials] = None) -> List[T]: parameters = URLParameters([ URLParameter('season', season.public_id), URLParameter('offset', offset), URLParameter('limit', limit), URLParameter('order_by', order_by.value), URLParameter('order', order.value) ]) if name_fragment is not None: parameters.append(URLParameter('fragment', name_fragment)) request = ApiRequest(path=cls._LIST_PATH, method=HTTPMethod.GET, data=None, url_parameters=parameters, credentials=credentials, configuration=configuration) return cls.optionally_decode_many(request.response_data, default_to_empty_list=True)
class Team(Decodable): _PATH = '/league/team' def __init__(self, league_id: str, picks: List[Pick], manager_id: str, manager_display_name: str, name: Optional[str], as_at: NozomiTime, as_at_round_sequence: int, composition: Composition) -> None: self._league_id = league_id self._picks = picks self._manager_id = manager_id self._manager_display_name = manager_display_name self._name = name self._as_at = as_at self._as_at_round_sequence = as_at_round_sequence self._composition = composition return league_id = Immutable(lambda s: s._league_id) picks = Immutable(lambda s: s._picks) manager_id = Immutable(lambda s: s._manager_id) manager_display_name = Immutable(lambda s: s._manager_display_name) name = Immutable(lambda s: s._name) total_points = Immutable(lambda s: s._total_points) as_at = Immutable(lambda s: s._as_at) as_at_round_sequence = Immutable(lambda s: s._as_at_round_sequence) filled_composition = Immutable(lambda s: s._compute_filled_composition()) def _compute_filled_composition(self) -> FilledComposition: filled_requirements: List[FilledRequirement] = list() remaining_picks = list(self._picks) for requirement in self._composition.position_requirements: picks_satisfying_requirement: List[Pick] = list() potential_picks = list(remaining_picks) for pick in potential_picks: if pick.score_card.has_position_with_name( name=requirement.position_name): picks_satisfying_requirement.append(pick) remaining_picks.remove(pick) continue filled_requirements.append( FilledRequirement(requirement=requirement, picks=picks_satisfying_requirement)) continue for category_requirement in self._composition.category_requirements: picks_satisfying_requirement: List[Pick] = list() potential_picks = list(remaining_picks) for pick in potential_picks: if pick.score_card.has_position_in_category( category=category_requirement.category): picks_satisfying_requirement.append(pick) remaining_picks.remove(pick) continue filled_requirements.append( FilledRequirement(requirement=category_requirement, picks=picks_satisfying_requirement)) continue return FilledComposition(requirements=filled_requirements) @classmethod def decode(cls: Type[T], data: Any) -> T: return cls(league_id=data['league_id'], picks=Pick.decode_many(data['picks']), manager_id=data['manager_id'], manager_display_name=data['manager_display_name'], name=data['name'], as_at=NozomiTime.decode(data['as_at']), as_at_round_sequence=data['as_at_round_sequence'], composition=Composition.decode(data['composition'])) @classmethod def retrieve(cls: Type[T], league_id: str, manager_id: str, credentials: RequestCredentials, configuration: Configuration, as_at_round: Optional[int] = None) -> Optional[T]: """ Return a Team in the supplied League, managed by the supplied Manager, if it exists. """ parameters = [ URLParameter('league', league_id), URLParameter('manager', manager_id) ] if as_at_round: parameters.append(URLParameter('as_at_round', as_at_round)) request = ApiRequest(path=cls._PATH, method=HTTPMethod.GET, configuration=configuration, data=None, url_parameters=URLParameters(parameters), credentials=credentials) return cls.optionally_decode(request.response_data)
class Season(Decodable): _PATH = '/fantasy/season' _LIST_PATH = '/fantasy/season/list' def __init__(self, public_id: str, name: str, start_date: NozomiDate, competition: Competition) -> None: self._public_id = public_id self._name = name self._start_date = start_date self._competition = competition return public_id = Immutable(lambda s: s._public_id) name = Immutable(lambda s: s._name) start_date = Immutable(lambda s: s._start_date) competition = Immutable(lambda s: s._competition) @classmethod def decode(cls: Type[T], data: Any) -> T: return cls(public_id=data['public_id'], name=data['name'], start_date=NozomiDate.decode(data['start_date']), competition=Competition.decode(data['competition'])) @classmethod def retrieve( cls: Type[T], public_id: str, configuration: Configuration, credentials: Optional[RequestCredentials] = None) -> Optional[T]: if not isinstance(public_id, str): raise TypeError('public_id must be of type `str`') parameters = URLParameters([URLParameter('public_id', public_id)]) request = ApiRequest(path=cls._PATH, method=HTTPMethod.GET, data=None, url_parameters=parameters, credentials=credentials, configuration=configuration) return cls.optionally_decode(request.response_data) @classmethod def retrieve_list( cls: Type[T], configuration: Configuration, credentials: Optional[RequestCredentials] = None) -> List[T]: request = ApiRequest(path=cls._LIST_PATH, method=HTTPMethod.GET, data=None, url_parameters=None, credentials=credentials, configuration=configuration) return cls.optionally_decode_many(request.response_data, default_to_empty_list=True)
class Session(NozomiAppSession): API_PATH = '/session' def __init__(self, session_id: str, session_key: str, api_key: str, agent: Agent, created: NozomiTime, last_utilised: NozomiTime, perspective: Perspective, requires_challenge: bool, has_completed_challenge: bool) -> None: assert isinstance(session_id, str) assert isinstance(session_key, str) assert isinstance(api_key, str) assert isinstance(agent, Agent) assert isinstance(created, NozomiTime) assert isinstance(last_utilised, NozomiTime) assert isinstance(perspective, Perspective) assert isinstance(requires_challenge, bool) assert isinstance(has_completed_challenge, bool) self._session_id = session_id self._session_key = session_key self._api_key = api_key self._agent = agent self._created = created self._last_utilised = last_utilised self._perspective = perspective self._requires_challenge = requires_challenge self._has_completed_challenge = has_completed_challenge return agent: Agent = Immutable(lambda s: s._agent) perspective: Perspective = Immutable(lambda s: s._perspective) api_key: str = Immutable(lambda s: s._api_key) session_id: int = Immutable(lambda s: s._session_id) has_completed_challenge: bool = Immutable( lambda s: s._has_completed_challenge) requires_challenge: bool = Immutable(lambda s: s._requires_challenge) agent_id = Immutable(lambda s: s._agent.agent_id) def delete(self, credentials: RequestCredentials, configuration: Configuration) -> None: """Delete this Session, AKA logout the user""" target = URLParameter('session_id', str(self._session_id)) parameters = URLParameters([target]) ApiRequest(path=self.API_PATH, method=HTTPMethod.DELETE, configuration=configuration, credentials=credentials, data=None, url_parameters=parameters) return None @classmethod def retrieve(cls: Type[T], session_id: str, credentials: RequestCredentials, configuration: Configuration) -> Optional[T]: """Return a Session with the given Session ID, if it exists""" assert isinstance(session_id, str) target = URLParameter('session_id', str(session_id)) parameters = URLParameters([target]) request = ApiRequest(path=cls.API_PATH, method=HTTPMethod.GET, configuration=configuration, credentials=credentials, data=None, url_parameters=parameters) if request.response_data is None: return None return cls.decode(request.response_data) @classmethod def create(cls: Type[T], email: str, secret: str, configuration: Configuration) -> T: data = {'email': email, 'secret': secret} raise NotImplementedError @classmethod def decode(cls: Type[T], data: Any) -> T: """Return a Session decoded from API response data""" return cls(data['session_id'], data['session_key'], data['api_key'], StandaloneAgent.decode(data), NozomiTime.decode(data['created']), NozomiTime.decode(data['last_utilised']), Perspective.with_id(data['perspective']), requires_challenge=data['requires_challenge'], has_completed_challenge=data['has_completed_challenge'])