implement slots, implement sorting to Availability

This commit is contained in:
2022-11-19 13:54:23 -06:00
parent 54d6dc410e
commit 287fd946b4
14 changed files with 252 additions and 249 deletions

View File

@@ -1,4 +1,4 @@
from .availability import Availability from .availability import Availability, AvailabilityStatusCode
from .availabilitysummary import AvailabilitySummary from .availabilitysummary import AvailabilitySummary
from .event import Event from .event import Event
from .eventlineup import EventLineup from .eventlineup import EventLineup
@@ -13,7 +13,7 @@ from .team import Team
from .user import User from .user import User
__all__ = [ __all__ = [
"Availability", "Availability", "AvailabilityStatusCode",
"AvailabilitySummary", "AvailabilitySummary",
"Event", "Event",
"EventLineup", "EventLineup",

View File

@@ -1,22 +1,56 @@
from .base import BaseApiObject from .base import BaseApiObject
from enum import Enum
class AvailabilityStatusCode(Enum):
YES = 1
MAYBE = 2
NO = 0
class Availability(BaseApiObject): class Availability(BaseApiObject):
rel = "availabilities" rel = "availabilities"
type = "availability" type = "availability"
version = "3.866.0" version = "3.866.0"
@property __slots__ = [
def data(self): "event_id",
"""Data dictionary for object "member_id",
"notes",
"notes_author_member_id",
"status",
"status_code",
"team_id",
"is_current_user",
]
:return: dict: dict with keys: def __str__(self):
- event_id return self.data.get('status')
- member_id
- notes def __repr__(self):
- notes_author_member_id return f'<TeamSnap {self.__class__.__name__} id={self.id} status_code={self.data.get("status_code")} status_="{self.data.get("status")}">'
- source
- status_code @classmethod
- type def __sort_value(cls, availability_obj):
""" if not isinstance(availability_obj, Availability):
return super().data raise TypeError(f"Cannot compare type {availability_obj.__class__} with {cls.__class__}")
return [
AvailabilityStatusCode.YES.value,
AvailabilityStatusCode.MAYBE.value,
AvailabilityStatusCode.NO.value,
None,
].index(availability_obj.status_code)
def __lt__(self, obj):
return (self.__sort_value(self) < (self.__sort_value(obj)))
def __gt__(self, obj):
return ((self.__sort_value(self)) > (self.__sort_value(obj)))
def __le__(self, obj):
return ((self.__sort_value(self)) <= (self.__sort_value(obj)))
def __ge__(self, obj):
return ((self.__sort_value(self)) >= (self.__sort_value(obj)))
def __eq__(self, obj):
return (self.__sort_value(self) == self.__sort_value(obj))

View File

@@ -6,10 +6,15 @@ class AvailabilitySummary(BaseApiObject):
type = "availability_summary" type = "availability_summary"
version = "3.866.0" version = "3.866.0"
@property __slots__ = [
def data(self): "event_id",
"""Data dictionary for object "team_id",
"going_count",
:return: dict: dict with keys: "not_going_count",
""" "maybe_count",
return super().data "unknown_count",
"player_going_count",
"player_not_going_count",
"player_maybe_count",
"player_unknown_count",
]

View File

@@ -4,17 +4,28 @@ from apiclient import (
APIClient, APIClient,
) )
import typing as T import typing as T
import copy from abc import ABC
from itertools import chain
# Import "preview" of Self typing # Import "preview" of Self typing
# https://stackoverflow.com/a/70932112 # https://stackoverflow.com/a/70932112
from typing_extensions import Self from typing_extensions import Self
class NotPossibleError(Exception):
"""Raised for actions that are not possible to perform this action per API"""
pass
class BaseApiObject: class BaseApiObject(ABC):
rel: str = None rel: str = None
version: str = None version: str = None
__slots__ = [
'client',
'id',
'id_',
]
def __init__( def __init__(
self, client: APIClient, data: T.Dict[str, T.Union[str, list]] = {} self, client: APIClient, data: T.Dict[str, T.Union[str, list]] = {}
) -> None: ) -> None:
@@ -24,31 +35,28 @@ class BaseApiObject:
:param data: Data to instantiate instance, defaults to empty dict. :param data: Data to instantiate instance, defaults to empty dict.
""" """
self.client = client self.client = client
slots = list(chain.from_iterable(getattr(cls, '__slots__', []) for cls in self.__class__.__mro__))
for k, v in data.items(): for k, v in data.items():
if k == 'type': continue if k == "id" :
if k == 'id': continue setattr(self, 'id', v) #TODO remove this, here for backward compatibility, but bad idea
setattr(self, k, v) setattr(self, 'id_', v)
self._internal_data_dict = copy.deepcopy(data) elif k in ['type', 'rel']: #read only, inherit to class type
self.rel = self.__class__.rel continue
"""rel: Relationship between a linked resource and the current document""" elif k in slots:
setattr(self, k, v)
else:
# print(f'Warning: {k} not in {self}')
pass
pass
def __str__(self):
return self.name
def __repr__(self): def __repr__(self):
return f'TeamSnap<{self.__class__.__name__}:{self.id}> "{self.data.get("name")}"' return f'<TeamSnap {self.__class__.__name__} id={self.id_} name="{self.rel}">'
def __getitem__(self, key):
return self._internal_data_dict.__getitem__(key)
# return getattr(self, key)
def __setitem__(self, key, newvalue):
return self._internal_data_dict.__setitem__(key, newvalue)
# return setattr(self, key, newvalue)
def __iter__(self):
return iter(self._internal_data_dict.items())
@property
def id(self) -> int:
return self._internal_data_dict["id"]
@property @property
def data(self) -> T.Dict[str, T.Union[str, list]]: def data(self) -> T.Dict[str, T.Union[str, list]]:
@@ -56,7 +64,8 @@ class BaseApiObject:
:return: dict: dict with keys: :return: dict: dict with keys:
""" """
return self._internal_data_dict slots = chain.from_iterable(getattr(cls, '__slots__', []) for cls in self.__class__.__mro__)
return {k:getattr(self, k, None) for k in slots}
@classmethod @classmethod
def search(cls, client: APIClient, **kwargs): def search(cls, client: APIClient, **kwargs):
@@ -82,7 +91,6 @@ class BaseApiObject:
} }
} }
r = self.client.post_item(self.rel, data=data) r = self.client.post_item(self.rel, data=data)
self._internal_data_dict = r
return self return self
def put(self) -> Self: def put(self) -> Self:
@@ -93,7 +101,6 @@ class BaseApiObject:
} }
id = self.data.get("id") id = self.data.get("id")
r = self.client.put_item(self.rel, id=id, data=data) r = self.client.put_item(self.rel, id=id, data=data)
self._internal_data_dict = r
return self return self
def delete(self): def delete(self):

View File

@@ -11,13 +11,15 @@ class Event(BaseApiObject):
type = "event" type = "event"
version = "3.866.0" version = "3.866.0"
__slots__ = ( __slots__ = [
# "type",
"additional_location_details", "additional_location_details",
"browser_time_zone", "arrival_date",
"division_location_id", "division_location_id",
"doesnt_count_towards_record", "doesnt_count_towards_record",
"duration_in_minutes", "duration_in_minutes",
"end_date",
"formatted_results",
"game_type",
"game_type_code", "game_type_code",
"icon_color", "icon_color",
"is_canceled", "is_canceled",
@@ -30,18 +32,12 @@ class Event(BaseApiObject):
"minutes_to_arrive_early", "minutes_to_arrive_early",
"name", "name",
"notes", "notes",
"notify_opponent",
"notify_opponent_contacts_email",
"notify_opponent_contacts_name",
"notify_opponent_notes",
"notify_team",
"notify_team_as_member_id",
"opponent_id", "opponent_id",
"points_for_opponent", "points_for_opponent",
"points_for_team", "points_for_team",
"repeating_include", "repeating_type",
"repeating_type_code", "repeating_type_code",
"repeating_until", "repeating_uuid",
"results", "results",
"results_url", "results_url",
"shootout_points_for_opponent", "shootout_points_for_opponent",
@@ -49,56 +45,20 @@ class Event(BaseApiObject):
"start_date", "start_date",
"team_id", "team_id",
"time_zone", "time_zone",
"time_zone_description",
"time_zone_iana_name",
"time_zone_offset",
"source_time_zone_iana_name",
"tracks_availability", "tracks_availability",
"uniform", "uniform",
) "is_league_controlled",
"opponent_name",
"location_name",
"formatted_title",
"formatted_title_for_multi_team",
"created_at",
"updated_at",
]
def __str__(self): def __str__(self):
return f'{self["formatted_title"]}' return f'{self.formatted_title}'
@property
def data(self):
"""Data dictionary for object
:return: dict: dict with strings:
- type
- additional_location_details
- browser_time_zone
- division_location_id
- doesnt_count_towards_record
- duration_in_minutes
- game_type_code
- icon_color
- is_canceled
- is_game
- is_overtime
- is_shootout
- is_tbd
- label
- location_id
- minutes_to_arrive_early
- name
- notes
- notify_opponent
- notify_opponent_contacts_email
- notify_opponent_contacts_name
- notify_opponent_notes
- notify_team
- notify_team_as_member_id
- opponent_id
- points_for_opponent
- points_for_team
- repeating_include
- repeating_type_code
- repeating_until
- results
- results_url
- shootout_points_for_opponent
- shootout_points_for_team
- start_date
- team_id
- time_zone
- tracks_availability
- uniform
"""
return super().data

View File

@@ -5,11 +5,9 @@ class EventLineup(BaseApiObject):
rel = "event_lineups" rel = "event_lineups"
type = "event_lineup" type = "event_lineup"
version = "3.866.0" version = "3.866.0"
template = {}
@property __slots__ = [
def data(self): "event_id",
""" "is_published",
:return: dict: dict with strings: "entries_count"
""" ]
return super().data

View File

@@ -6,16 +6,16 @@ class EventLineupEntry(BaseApiObject):
type = "event_lineup_entry" type = "event_lineup_entry"
version = "3.866.0" version = "3.866.0"
@property __slots__ = [
def data(self): "event_lineup_id",
""" "event_id",
:return: dict: dict with strings: "member_id",
- member_id "sequence",
- sequence "label",
- label "member_name",
- type "member_photo",
""" "availability_status_code"
return super().data ]
@classmethod @classmethod
def search(cls, client, **kwargs): def search(cls, client, **kwargs):

View File

@@ -6,20 +6,14 @@ class Location(BaseApiObject):
type = "location" type = "location"
version = "3.866.0" version = "3.866.0"
@property __slots__ = [
def data(self): 'name',
"""Data dictionary for object 'url',
'phone',
:return: dict: dict with keys: 'notes',
- name 'address',
- url 'latitude',
- phone 'longitude',
- notes 'team_id',
- address 'is_retired',
- latitude ]
- longitude
- team_id
- is_retired
- type
"""
return super().data

View File

@@ -11,31 +11,31 @@ class Member(BaseApiObject):
type = "member" type = "member"
version = "3.866.0" version = "3.866.0"
@property __slots__ = [
def data(self): 'first_name',
"""Data dictionary for object 'last_name',
'address_city',
'address_state',
'address_street1',
'address_street2',
'address_zip',
'birthday',
'gender',
'hide_address',
'hide_age',
'is_address_hidden',
'is_age_hidden',
'is_manager',
'is_non_player',
'is_ownership_pending',
'jersey_number',
'position',
'source_action',
'team_id',
]
:return: dict: dict with keys: def __str__(self):
- first_name return f"{self.first_name} {self.last_name}"
- last_name
- address_city def __repr__(self):
- address_state return f'<TeamSnap {self.__class__.__name__} id={self.id} first_name="{self.first_name}" last_name="{self.last_name}">'
- address_street1
- address_street2
- address_zip
- birthday
- gender
- hide_address
- hide_age
- is_address_hidden
- is_age_hidden
- is_manager
- is_non_player
- is_ownership_pending
- jersey_number
- position
- source_action
- team_id
- type
"""
return super().data

View File

@@ -3,3 +3,18 @@ from .base import BaseApiObject
class MemberStatistics(BaseApiObject): class MemberStatistics(BaseApiObject):
rel = "member_statistics" rel = "member_statistics"
type = "member_statistic"
__slots__ = [
"id",
"count_games_played",
"total",
"average",
"total_ranking",
"average_ranking",
"total_ranking_for_query",
"average_ranking_for_query",
"statistic_id",
"member_id",
"team_id",
]

View File

@@ -6,17 +6,11 @@ class Opponent(BaseApiObject):
type = "opponent" type = "opponent"
version = "3.866.0" version = "3.866.0"
@property __slots__ = [
def data(self): 'name',
"""Data dictionary for object 'contacts_name',
'contacts_phone',
:return: dict: dict with keys: 'contacts_email',
- name 'notes',
- contacts_name 'team_id',
- contacts_phone ]
- contacts_email
- notes
- team_id
- type
"""
return super().data

View File

@@ -6,24 +6,19 @@ class Statistics(BaseApiObject):
type = "statistic" type = "statistic"
version = "3.866.0" version = "3.866.0"
@property __slots__ = [
def data(self): 'acronym',
"""Data dictionary for object 'always_display_decimals',
'formula',
'is_in_descending_order',
'display_zero_totals',
'is_percentage',
'is_private',
'is_team_statistic',
'is_top_statistic',
'name',
'precision',
'statistic_group_id',
'team_id',
]
:return: dict: dict with keys:
- acronym
- always_display_decimals
- formula
- is_in_descending_order
- display_zero_totals
- is_percentage
- is_private
- is_team_statistic
- is_top_statistic
- name
- precision
- statistic_group_id
- team_id
- type
"""
return super().data

View File

@@ -12,32 +12,23 @@ class Team(BaseApiObject):
type = "team" type = "team"
version = "3.866.0" version = "3.866.0"
# Override this class property to add docstring __slots__ = [
# should not change functionality. Probably a better 'ad_unit_hero_id',
# to do this... 'ad_unit_hero_template_id',
@property 'ad_unit_inline_id',
def data(self): 'division_id',
"""Data dictionary for object 'division_name',
'is_ownership_pending',
:return: dict: dict with keys: 'league_name',
- ad_unit_hero_id 'league_url',
- ad_unit_hero_template_id 'location_country',
- ad_unit_inline_id 'location_postal_code',
- division_id 'name',
- division_name 'owner_email',
- is_ownership_pending 'owner_first_name',
- league_name 'owner_last_name',
- league_url 'season_name',
- location_country 'sport_id',
- location_postal_code 'team',
- name 'time_zone',
- owner_email ]
- owner_first_name
- owner_last_name
- season_name
- sport_id
- team
- time_zone
- type
"""
return super().data

View File

@@ -1,28 +1,38 @@
from .base import BaseApiObject from .base import BaseApiObject, NotPossibleError
class User(BaseApiObject): class User(BaseApiObject):
rel = "users" rel = "users"
type = "user" type = "user"
version = "3.866.0" version = "3.866.0"
__slots__ = [
'first_name',
'last_name',
'password',
'birthday',
'email',
'facebook_id',
'facebook_access_token',
'is_lab_rat',
'receives_newsletter',
]
def __str__(self): def __str__(self):
return f'{self["first_name"]} {self["last_name"]}' return f'{self["first_name"]} {self["last_name"]}'
@property def delete(self):
def data(self): """It is not possible to create or delete users via the API;
"""Data dictionary for object however, it is possible to update data on a user's record."""
raise NotPossibleError ('It is not possible to delete users via the API')
:return: dict: dict with keys: def new(self):
- first_name """It is not possible to create or delete users via the API;
- last_name however, it is possible to update data on a user's record."""
- password raise NotPossibleError('It is not possible to create users via the API')
- birthday
- email def post(self):
- facebook_id """It is not possible to create or delete users via the API;
- facebook_access_token however, it is possible to update data on a user's record."""
- type raise NotPossibleError('It is not possible to create users via the API')
- is_lab_rat
- receives_newsletter
"""
return super().data