def _merge_field( datasource_series: List[Tuple[str, pd.Series]], new_index, log: structlog.BoundLoggerBase ): log.info("Working field") field_out = None field_provenance = pd.Series(index=new_index, dtype="object") # Go through the data sources, starting with the highest priority. for datasource_name, datasource_field_in in reversed(datasource_series): log_datasource = log.bind(dataset_name=datasource_name) if field_out is None: # Copy all values from the highest priority input to the output field_provenance.loc[pd.notna(datasource_field_in)] = datasource_name field_out = datasource_field_in else: field_out_has_ts = field_out.groupby(level=[CommonFields.FIPS], sort=False).transform( lambda x: x.notna().any() ) copy_field_in = (~field_out_has_ts) & pd.notna(datasource_field_in) # Copy from datasource_field_in only on rows where all rows of field_out with that FIPS are NaN. field_provenance.loc[copy_field_in] = datasource_name field_out = field_out.where(~copy_field_in, datasource_field_in) dups = field_out.index.duplicated(keep=False) if dups.any(): log_datasource.error("Found duplicates in index") raise ValueError() # This is bad, somehow the input /still/ has duplicates return field_out, field_provenance
def log_transaction(log: BoundLoggerBase, description: str, details: Dict[Any, Any]) -> Generator: bound_log = log.bind(description=description, **details) try: bound_log.debug("Entered") yield except: # noqa bound_log.critical("Failed", exc_info=True) raise bound_log.debug("Exited")
async def on_join_game(*, log: Logger, ctx: ServerCtx, conn_id: str, msg_id: int, payload: dict): game_id: str = payload['game_id'] player: Player = payload['player'] log = log.bind(game_id=game_id, player=player) game_id_bytes = uuid.UUID(game_id).bytes session_state, _ = await ctx.redis_store.read_session(conn_id) if session_state != SessionState.NEED_JOIN: log.msg('unexpected session state', session_state=session_state.value) await ctx.send_fatal( conn_id, wire.ServerMsgType.ILLEGAL_MSG, error='session is not awaiting join', err_msg_id=msg_id, ) return meta = await ctx.redis_store.read_game_meta(game_id_bytes) if not await validate_join_request( ctx, log=log, player=player, meta=meta): log.msg('player already claimed') await ctx.send_fatal( conn_id, wire.ServerMsgType.ILLEGAL_MSG, error='player has already been claimed', err_msg_id=msg_id, ) return meta = meta.with_conn_id(player, conn_id) # TODO: validate state transitions? await asyncio.gather( ctx.redis_store.update_game(game_id_bytes, meta=meta), ctx.redis_store.put_session(conn_id, SessionState.NEED_JOIN_ACK, game_id_bytes), ) # XXX: org? _, game = await ctx.redis_store.read_game(game_id_bytes) try: await ctx.send( conn_id, wire.ServerMsgType.GAME_JOINED, game_id=game_id, player=player, player_nonce=str(meta.get_player_nonce(player)), squares_per_row=game.squares, run_to_win=game.target_len, ) except WebsocketConnectionLost: log.msg('connection lost') # Roll back game updates... meta = meta.with_state(GameState.JOIN_PENDING).with_conn_id( player, None) await asyncio.gather( ctx.redis_store.delete_session(conn_id), ctx.redis_store.update_game(game_id_bytes, meta=meta), )