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 .event import Event
from .eventlineup import EventLineup
@@ -13,7 +13,7 @@ from .team import Team
from .user import User
__all__ = [
"Availability",
"Availability", "AvailabilityStatusCode",
"AvailabilitySummary",
"Event",
"EventLineup",

View File

@@ -1,22 +1,56 @@
from .base import BaseApiObject
from enum import Enum
class AvailabilityStatusCode(Enum):
YES = 1
MAYBE = 2
NO = 0
class Availability(BaseApiObject):
rel = "availabilities"
type = "availability"
version = "3.866.0"
@property
def data(self):
"""Data dictionary for object
__slots__ = [
"event_id",
"member_id",
"notes",
"notes_author_member_id",
"status",
"status_code",
"team_id",
"is_current_user",
]
:return: dict: dict with keys:
- event_id
- member_id
- notes
- notes_author_member_id
- source
- status_code
- type
"""
return super().data
def __str__(self):
return self.data.get('status')
def __repr__(self):
return f'<TeamSnap {self.__class__.__name__} id={self.id} status_code={self.data.get("status_code")} status_="{self.data.get("status")}">'
@classmethod
def __sort_value(cls, availability_obj):
if not isinstance(availability_obj, Availability):
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"
version = "3.866.0"
@property
def data(self):
"""Data dictionary for object
:return: dict: dict with keys:
"""
return super().data
__slots__ = [
"event_id",
"team_id",
"going_count",
"not_going_count",
"maybe_count",
"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,
)
import typing as T
import copy
from abc import ABC
from itertools import chain
# Import "preview" of Self typing
# https://stackoverflow.com/a/70932112
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
version: str = None
__slots__ = [
'client',
'id',
'id_',
]
def __init__(
self, client: APIClient, data: T.Dict[str, T.Union[str, list]] = {}
) -> None:
@@ -24,31 +35,28 @@ class BaseApiObject:
:param data: Data to instantiate instance, defaults to empty dict.
"""
self.client = client
slots = list(chain.from_iterable(getattr(cls, '__slots__', []) for cls in self.__class__.__mro__))
for k, v in data.items():
if k == 'type': continue
if k == 'id': continue
setattr(self, k, v)
self._internal_data_dict = copy.deepcopy(data)
self.rel = self.__class__.rel
"""rel: Relationship between a linked resource and the current document"""
if k == "id" :
setattr(self, 'id', v) #TODO remove this, here for backward compatibility, but bad idea
setattr(self, 'id_', v)
elif k in ['type', 'rel']: #read only, inherit to class type
continue
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):
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
def data(self) -> T.Dict[str, T.Union[str, list]]:
@@ -56,7 +64,8 @@ class BaseApiObject:
: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
def search(cls, client: APIClient, **kwargs):
@@ -82,7 +91,6 @@ class BaseApiObject:
}
}
r = self.client.post_item(self.rel, data=data)
self._internal_data_dict = r
return self
def put(self) -> Self:
@@ -93,7 +101,6 @@ class BaseApiObject:
}
id = self.data.get("id")
r = self.client.put_item(self.rel, id=id, data=data)
self._internal_data_dict = r
return self
def delete(self):

View File

@@ -11,13 +11,15 @@ class Event(BaseApiObject):
type = "event"
version = "3.866.0"
__slots__ = (
# "type",
__slots__ = [
"additional_location_details",
"browser_time_zone",
"arrival_date",
"division_location_id",
"doesnt_count_towards_record",
"duration_in_minutes",
"end_date",
"formatted_results",
"game_type",
"game_type_code",
"icon_color",
"is_canceled",
@@ -30,18 +32,12 @@ class Event(BaseApiObject):
"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",
"repeating_type_code",
"repeating_until",
"repeating_uuid",
"results",
"results_url",
"shootout_points_for_opponent",
@@ -49,56 +45,20 @@ class Event(BaseApiObject):
"start_date",
"team_id",
"time_zone",
"time_zone_description",
"time_zone_iana_name",
"time_zone_offset",
"source_time_zone_iana_name",
"tracks_availability",
"uniform",
)
"is_league_controlled",
"opponent_name",
"location_name",
"formatted_title",
"formatted_title_for_multi_team",
"created_at",
"updated_at",
]
def __str__(self):
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
return f'{self.formatted_title}'

View File

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

View File

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

View File

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

View File

@@ -11,31 +11,31 @@ class Member(BaseApiObject):
type = "member"
version = "3.866.0"
@property
def data(self):
"""Data dictionary for object
__slots__ = [
'first_name',
'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:
- first_name
- 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
- type
"""
return super().data
def __str__(self):
return f"{self.first_name} {self.last_name}"
def __repr__(self):
return f'<TeamSnap {self.__class__.__name__} id={self.id} first_name="{self.first_name}" last_name="{self.last_name}">'

View File

@@ -3,3 +3,18 @@ from .base import BaseApiObject
class MemberStatistics(BaseApiObject):
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"
version = "3.866.0"
@property
def data(self):
"""Data dictionary for object
:return: dict: dict with keys:
- name
- contacts_name
- contacts_phone
- contacts_email
- notes
- team_id
- type
"""
return super().data
__slots__ = [
'name',
'contacts_name',
'contacts_phone',
'contacts_email',
'notes',
'team_id',
]

View File

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

View File

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