def decorated_function(*args: List[Any], **kwargs: Dict[str, Any]) -> Callable: cache_key = key.format(id=request.full_path, locale=localization.get_locale()) # include querystring cache_policy = '' if not cacheable: cache_policy += ', no-store' # tells the browser not to cache at all else: if must_revalidate: # this looks contradicting if you haven't read the article. # no-cache doesn't mean "don't cache", it means it must check # (or "revalidate" as it calls it) with the server before # using the cached resource cache_policy += ', no-cache' else: # Also must-revalidate doesn't mean "must revalidate", it # means the local resource can be used if it's younger than # the provided max-age, otherwise it must revalidate cache_policy += ', must-revalidate' if client_only: cache_policy += ', private' else: cache_policy += ', public' actual_client_timeout = client_timeout actual_server_timeout = server_timeout if get_season_id() and get_season_id() != 0 and get_season_id() < seasons.current_season_num(): actual_client_timeout = 7 * 24 * 60 * 60 actual_server_timeout = 7 * 24 * 60 * 60 cache_policy += ', max-age={client_timeout}'.format(client_timeout=actual_client_timeout) headers = {} cache_policy = cache_policy.strip(',') headers['Cache-Control'] = cache_policy now = datetime.datetime.utcnow() client_etag = request.headers.get('If-None-Match') response = CACHE.get(cache_key) # type: ignore # Respect a hard refresh from the client, if sent. # Note: Safari/OSX does not send a Cache-Control (or any additional) header on a hard refresh so people using Safari can't bypass/refresh server cache. if response is not None and request.headers.get('Cache-Control', '') != 'no-cache': headers['X-Cache'] = 'HIT from Server' cached_etag = response.headers.get('ETag') if client_etag and cached_etag and client_etag == cached_etag: headers['X-Cache'] = 'HIT from Client' headers['X-Last-Modified'] = response.headers.get('X-LastModified') response = make_response('', 304) else: response = make_response(f(*args, **kwargs)) if response.status_code == 200 and request.method in ['GET', 'HEAD']: headers['X-Cache'] = 'MISS' # - Added the headers to the response object instead of the # headers dict so they get cached too # - If you can find any faster random algorithm go for it. response.headers.add('ETag', binascii.hexlify(os.urandom(4))) response.headers.add('X-Last-Modified', str(now)) CACHE.set(cache_key, response, timeout=actual_server_timeout) response.headers.extend(headers) return response
def card_history(c: Card) -> str: data: Dict[int, bool] = {} for format_name, status in c.legalities.items(): if 'Penny Dreadful ' in format_name and status == 'Legal': season_id = seasons.SEASONS.index( format_name.replace('Penny Dreadful ', '')) + 1 data[season_id] = True data[seasons.current_season_num()] = c.legalities.get('Penny Dreadful', None) == 'Legal' s = ' ' for i in range(1, seasons.current_season_num() + 1): s += f'{i} ' s += ':white_check_mark:' if data.get(i, False) else ':no_entry_sign:' s += ' ' s = s.strip() s += '\n<' + fetcher.decksite_url('/seasons/all/cards/{name}/'.format( name=fetch_tools.escape(c.name, skip_double_slash=True))) + '>' return s
def title(self) -> str: if not self.page_title(): return 'pennydreadfulmagic.com' if get_season_id() == seasons.current_season_num(): season = '' elif get_season_id() == 0: season = ' - All Time' else: season = ' - Season {n}'.format(n=get_season_id()) return '{page_title}{season} – pennydreadfulmagic.com'.format(page_title=self.page_title(), season=season)
def before_request() -> Optional[wrappers.Response]: if not request.path.endswith('/'): return None # Let flask do the redirect-routes-not-ending-in-slashes thing before we interfere with routing. Avoids #8277. if request.path.startswith('/seasons') and len(request.path) > len( '/seasons/') and get_season_id() >= seasons.current_season_num(): return redirect(re.sub('/seasons/[^/]*', '', request.path)) if request.path.startswith('/seasons/0'): return redirect(request.path.replace('/seasons/0', '/seasons/all')) g.p = perf.start() return None
def person_api(person: str, season_id: int = -1) -> Response: if season_id == -1: season_id = seasons.current_season_num() try: p = ps.load_person_by_discord_id_or_username(person, season_id) p.decks_url = url_for('person_decks_api', person=person, season_id=season_id) return return_json(p) except DoesNotExistException: return return_json(generate_error('NOTFOUND', 'Person does not exist'))
def seasonized_url(season_id: Union[int, str]) -> str: args = request.view_args.copy() if season_id == seasons.current_season_num(): args.pop('season_id', None) endpoint = cast(str, request.endpoint).replace('seasons.', '') else: args['season_id'] = season_id prefix = '' if cast(str, request.endpoint).startswith('seasons.') else 'seasons.' endpoint = '{prefix}{endpoint}'.format(prefix=prefix, endpoint=request.endpoint) try: return url_for(endpoint, **args) except BuildError: return url_for(cast(str, request.endpoint))
def pd_rotation_changes( season_id: int) -> Tuple[Sequence[Card], Sequence[Card]]: # It doesn't really make sense to do this for 'all' so just show current season in that case. if season_id == 0: season_id = seasons.current_season_num() try: from_format_id = multiverse.get_format_id_from_season_id( int(season_id) - 1) except InvalidArgumentException: from_format_id = -1 try: to_format_id = multiverse.get_format_id_from_season_id(season_id) except InvalidArgumentException: to_format_id = -1 return changes_between_formats(from_format_id, to_format_id)
def h2h_api() -> Response: """ Grab a slice of results from a 0-indexed resultset of head-to-head entries. Input: { 'page': <int>, 'pageSize': <int>, 'personId': <int>, 'sortBy': <str>, 'sortOrder': <'ASC'|'DESC'>, 'seasonId': <int|'all'>, 'q': <str> } Output: { 'page': <int>, 'objects': [<entry>], 'total': <int> } """ order_by = query.head_to_head_order_by(request.args.get('sortBy'), request.args.get('sortOrder')) page_size = int(request.args.get('pageSize', DEFAULT_LIVE_TABLE_PAGE_SIZE)) page = int(request.args.get('page', 0)) start = page * page_size limit = f'LIMIT {start}, {page_size}' season_id = seasons.season_id(str(request.args.get('seasonId')), None) person_id = int(request.args.get('personId', 0)) q = request.args.get('q', '').strip() where = query.text_match_where('opp.mtgo_username', q) if q else 'TRUE' entries = ps.load_head_to_head(person_id, where=where, order_by=order_by, limit=limit, season_id=season_id) for entry in entries: entry.opp_url = url_for('.person', mtgo_username=entry.opp_mtgo_username, season_id=None if season_id == seasons.current_season_num() else season_id) total = ps.load_head_to_head_count(person_id=person_id, where=where, season_id=season_id) r = {'page': page, 'total': total, 'objects': entries} resp = return_json(r, camelize=True) resp.set_cookie('page_size', str(page_size)) return resp
def setup_active_seasons(self, seasons_active: Sequence[int]) -> None: total_seasons = len(seasons.SEASONS) cube_side_length = round(math.sqrt(total_seasons)) self.seasons_active = [] for i, setcode in enumerate(reversed(seasons.SEASONS)): season_id = total_seasons - i if season_id > seasons.current_season_num(): continue active = season_id in seasons_active self.seasons_active.append({ 'season_id': season_id, 'className': f'ss-{setcode.lower()} ' + ('ss-common' if active else 'inactive'), 'url': url_for('seasons.person', person_id=self.person.id, season_id=season_id) if active else '', 'edge': (i + 1) % cube_side_length == 0, })
def get_season_id() -> int: season_id = g.get('season_id', seasons.current_season_num()) if season_id == 'all': return 0 return season_id
def __init__(self, person: ps.Person, cards: List[Card], archetypes: List[Archetype], all_archetypes: List[Archetype], your_cards: Dict[str, List[str]], seasons_active: Sequence[int], season_id: Optional[int]) -> None: super().__init__() self.all_archetypes = all_archetypes self.person = person self.people = [person] self.decks = person.decks self.has_decks = len(person.decks) > 0 self.archetypes = archetypes self.hide_person = True self.cards = cards self.show_seasons = True self.displayed_achievements = [{ 'title': a.title, 'detail': titlecase.titlecase(a.display(self.person)) } for a in Achievement.all_achievements if a.display(self.person)] self.achievements_url = url_for('.achievements') self.person_achievements_url = url_for('.person_achievements', person_id=person.id) colors: Dict[str, int] = {} for d in self.decks: for c in d.colors: colors[c] = colors.get(c, 0) + 1 self.charts = [ { 'title': 'Colors Played', 'type': 'horizontalBar', 'labels': json.dumps( ['White', 'Blue', 'Black', 'Red', 'Green', 'Colorless']), 'series': json.dumps([ colors.get('W'), colors.get('U'), colors.get('B'), colors.get('R'), colors.get('G'), colors.get('C') ]), 'options': json.dumps({ 'responsive': True, 'scales': { 'xAxes': [{ 'ticks': { 'precision': 0 } }] } }), # Only display whole numbers on x axis. }, ] self.add_note_url = url_for('post_player_note') self.matches_url = url_for( '.person_matches', person_id=person.id, season_id=None if season_id == seasons.current_season_num() else season_id) self.is_person_page = True self.trailblazer_cards = oracle.load_cards(your_cards['trailblazer']) self.has_trailblazer_cards = len(self.trailblazer_cards) > 0 self.unique_cards = oracle.load_cards(your_cards['unique']) self.has_unique_cards = len(self.unique_cards) > 0 self.cards += self.trailblazer_cards + self.unique_cards self.setup_active_seasons(seasons_active)
def random_legal_deck() -> Optional[Deck]: where = 'd.reviewed AND d.created_date > (SELECT start_date FROM season WHERE number = {current_season_num})'.format(current_season_num=seasons.current_season_num()) having = '(d.competition_id NOT IN ({active_competition_id_query}) OR SUM(cache.wins + cache.draws + cache.losses) >= 5)'.format(active_competition_id_query=active_competition_id_query()) try: return deck.load_decks(where=where, having=having, order_by='RAND()', limit='LIMIT 1')[0] except IndexError: # For a short while at the start of a season there are no decks that match the WHERE/HAVING clauses. return None
def test_seasonized_url_for_app() -> None: with APP.test_request_context('/decks/'): assert view.seasonized_url(1) == '/seasons/1/decks/' assert view.seasonized_url(seasons.current_season_num()) == '/decks/'
def test_seasonized_url_simple() -> None: with APP.test_request_context('/tournaments/'): assert view.seasonized_url(1) == '/tournaments/' assert view.seasonized_url( seasons.current_season_num()) == '/tournaments/'