def getActiveSeasonEvents(self): """Get active (current) season events.""" _current_season_events_attrs = [ 'current_season_events', 'eventdays', 'eventchannel' ] if not any([hasattr(self, a) for a in _current_season_events_attrs ]) or not _checkattr(self, 'current_season_events'): self.fetchActiveSeasonEvents() return (self.current_season_events, self.eventdays, self.eventchannel)
def _checkRallyId(self, sdbRallyId=None): """Return a rally ID or lookup active one.""" sdbRallyId = _jsInt(sdbRallyId) or self.sdbRallyId if not _checkattr(self, 'sdbRallyId'): self.activerally = WRCActiveRally() self.sdbRallyId = self.activerally.sdbRallyId self.name = self.activerally.name return self.sdbRallyId
def _checkItinerary(self): """ Check itinerary. If rally not known, use active rally. Also set a default startListId. """ _itinerary_items = [ 'itinerary', 'legs', 'sections', 'controls', 'stages' ] if not all([_checkattr(self, i) for i in _itinerary_items]): self.fetchItinerary()
def db_connect(self, dbname=None): """ Connect to a db. Give the file a randomly generated name if one not provided. """ dbname = dbname or f'{uuid.uuid4().hex}.db' if not _checkattr(self, dbname) or (dbname and self.dbname != dbname): self.dbname = dbname else: self.dbname = dbname self.db = Database(self.dbname)
def getStageIdsFromCode(self, codes=None, response='dict'): """Return a stageID from one or more codes.""" # TO DO: this should really run through getStageIdFromCode() codes = [f'SS{_jsInt(c)}' if _jsInt(c) else c for c in listify(codes)] if codes and _checkattr(self, 'stages'): _df = self.stages[self.stages['code'].isin(codes)][[ 'code', 'rallyid', 'stageId' ]] if response == 'df': return _df elif response == 'tuples': return list(_df.itertuples(index=False, name=None)) return _df.set_index('code').to_dict(orient='index')
def getStageIdFromCode(self, code=None): """Return a stageID from a single codes.""" # Accept: 'SS1', '1', 1 if _jsInt(code): code = f'SS{code}' if code and isinstance(code, str) and _checkattr(self, 'stages'): _df = self.stages[self.stages['code'] == code][[ 'rallyid', 'stageId' ]] return tuple(_df.iloc[0]) elif code and isinstance(code, list): # TO DO - this might be dangerous if we are expecting a single tuple response return getStageIdsFromCode(code, response='tuples')
def call(self): """Check attributes. If any missing, grab data as required.""" (attrs, func2) = func(self) if not attrs: return None if isinstance(attrs, str): attrs = [attrs] # Don't call the function if all the attributes that would be set # by calling it are already set. if not all([_checkattr(self, a) for a in attrs]): func2() if len(attrs) > 1: return tuple(getattr(self, a) for a in attrs) return getattr(self, attrs[0])
def getStageIds(self, typ='all', response='dict'): """Return stageIDs by stage status.""" if _checkattr(self, 'stages'): if typ == 'all': _df = self.stages[['code', 'rallyid', 'stageId']] else: if typ == 'completed': _statuses = ['Completed', 'Interrupted'] elif typ == 'onlycompleted': _statuses = ['Completed'] elif typ == 'interrupted': _statuses = ['Interrupted'] _df = self.stages[self.stages['status'].isin(_statuses)][[ 'code', 'rallyid', 'stageId' ]] if response == 'df': return _df elif response == 'tuples': return list(_df.itertuples(index=False, name=None)) return _df.set_index('code').to_dict(orient='index')
def mongodb_checkconn(self, host=None, port=None): """Check existence of a MongoDB connection and try to create it otherwise.""" if not _checkattr(self, 'mongo_conn'): self.mongodb_connect(host, port)
def _checkStages(self, sdbRallyId=None): """Return a stages list or lookup list for active rally.""" # Have we got an sdbRallyId? if not _checkattr(self, 'stages'): self.fetchStages(sdbRallyId=None)
def _check_season_external_id(self, season_external_id=None): """Check that season_external_id exists and if not, get one.""" self.season_external_id = _jsInt( season_external_id) or self.season_external_id if not _checkattr(self, 'season_external_id'): self.fetchSeasonExternalId(season_external_id)
def upsert(self, table, data=None, pk=None): """ Upsert data to database. If we forget to create a database, this will create one. """ print(f'upserting into {table}') _upserts = [] if isinstance(table, str): if _notnull(data) and pk is not None: # One table _upserts.append((table, data, pk)) # Check data is None. It may be {}, which would be data... elif hasattr(self, table) and data is None and pk is not None: # One table, data from self attribute data = getattr(self, table) _upserts.append((table, data, pk)) elif isinstance(table, tuple) and len(table) == 2 and _isnull(data): (_table, _pk) = table if isinstance(_table, str) and hasattr(self, _table) and _pk is not None: _data = getattr(self, _table) _upserts.append((_table, _data, _pk)) elif isinstance(table, list) and _isnull(data): # Several tables from self attributes: [(table, pk), ..] for _t in table: if isinstance(_t, tuple) and len(_t) == 2: (_table, _pk) = _t if isinstance(_table, str) and hasattr( self, _table) and _pk is not None: _data = getattr(self, _table) _upserts.append((_table, _data, _pk)) # TO DO - if the pk is none, and data is a df, use the df index? if not _checkattr(self, 'dbname') and not _checkattr(self, 'db'): self.db_connect() # The alter=True allows us the table to be modified if we have extra columns for (_table, _data, _pk) in _upserts: # TO DO - the try is to cope with this issue: # https://github.com/simonw/sqlite-utils/issues/73#issuecomment-571138093 # The ignore does not result in a dupe: the original row is left in place if isinstance( _data, pd.DataFrame) and _notnull(_data) and _pk is not None: try: self.db[_table].upsert_all(_data.to_dict(orient='records'), pk=_pk, alter=True) except: try: self.db[_table].insert_all( _data.to_dict(orient='records'), pk=_pk, alter=True, replace=True) except: warning(f"Couldn't add data to {_table} with PK {_pk}") elif isinstance(_data, dict) and _data and _pk is not None: try: self.db[_table].upsert_all(_data, pk=_pk, alter=True) except: try: self.db[_table].insert_all(_data, pk=_pk, alter=True, replace=True) except: warning(f"Couldn't add data to {_table} with PK {_pk}")
def getRally(self): """Get external rally details.""" attrs = ['rally', 'eligibilities', 'groups'] if not all([_checkattr(self, a) for a in attrs]): self.fetchRally() return tuple(getattr(self, a) for a in attrs)