class TopicListingSchema(Schema): """Marshmallow schema to validate arguments for a topic listing page.""" DEFAULT_TOPICS_PER_PAGE = 50 order = Enum(TopicSortOption) period = ShortTimePeriod(allow_none=True) after = ID36() before = ID36() per_page = Integer( validate=Range(min=1, max=100), missing=DEFAULT_TOPICS_PER_PAGE, ) rank_start = Integer(load_from='n', validate=Range(min=1), missing=None) tag = Ltree(missing=None) unfiltered = Boolean(missing=False) @validates_schema def either_after_or_before(self, data: dict) -> None: """Fail validation if both after and before were specified.""" if data.get('after') and data.get('before'): raise ValidationError("Can't specify both after and before.") @pre_load def reset_rank_start_on_first_page(self, data: dict) -> dict: """Reset rank_start to 1 if this is a first page (no before/after).""" if not (data.get('before') or data.get('after')): data['rank_start'] = 1 return data class Meta: """Always use strict checking so error handlers are invoked.""" strict = True
def _get_default_settings(request: Request, order: Any) -> DefaultSettings: if isinstance(request.context, Group): is_home_page = False user_settings = (request.query(UserGroupSettings).filter( UserGroupSettings.user == request.user, UserGroupSettings.group == request.context, ).one_or_none()) else: is_home_page = True user_settings = None if user_settings and user_settings.default_order: default_order = user_settings.default_order elif request.user.home_default_order: default_order = request.user.home_default_order else: default_order = TopicSortOption.ACTIVITY # the default period depends on what the order is, so we need to see if # we're going to end up using the default order here as well if order is missing: order = default_order if user_settings and user_settings.default_period: user_default = user_settings.default_period default_period = ShortTimePeriod().deserialize(user_default) elif request.user.home_default_period: user_default = request.user.home_default_period default_period = ShortTimePeriod().deserialize(user_default) else: # Overall default periods, if the user doesn't have either a # group-specific or a home default set up: # * "all time" if sorting by new # * "all time" if sorting by activity and inside a group # * "3 days" if sorting by activity and on home page # * "1 day" otherwise (sorting by most votes or most comments) if order == TopicSortOption.NEW: default_period = None elif order == TopicSortOption.ACTIVITY and not is_home_page: default_period = None elif order == TopicSortOption.ACTIVITY: default_period = SimpleHoursPeriod(72) else: default_period = SimpleHoursPeriod(24) return DefaultSettings(order=default_order, period=default_period)
def _get_default_settings( request: Request, order: Optional[TopicSortOption] ) -> DefaultSettings: if isinstance(request.context, Group) and request.user: user_settings = ( request.query(UserGroupSettings) .filter( UserGroupSettings.user == request.user, UserGroupSettings.group == request.context, ) .one_or_none() ) else: user_settings = None if user_settings and user_settings.default_order: default_order = user_settings.default_order elif request.user and request.user.home_default_order: default_order = request.user.home_default_order else: default_order = TopicSortOption.ACTIVITY # the default period depends on what the order is, so we need to see if we're going # to end up using the default order here as well if not order: order = default_order if user_settings and user_settings.default_period: user_default = user_settings.default_period default_period = ShortTimePeriod().deserialize(user_default) elif request.user and request.user.home_default_period: user_default = request.user.home_default_period default_period = ShortTimePeriod().deserialize(user_default) else: # Overall default periods, if the user doesn't have either a group-specific or a # home default set up: # * "1 day" if sorting by most votes or most comments # * "all time" otherwise if order in (TopicSortOption.VOTES, TopicSortOption.COMMENTS): default_period = SimpleHoursPeriod(24) else: default_period = None return DefaultSettings(order=default_order, period=default_period)
class TopicListingSchema(PaginatedListingSchema): """Marshmallow schema to validate arguments for a topic listing page.""" period = ShortTimePeriod(allow_none=True) order = Enum(TopicSortOption) tag = Ltree(missing=None) unfiltered = Boolean(missing=False) rank_start = Integer(load_from="n", validate=Range(min=1), missing=None) @pre_load def reset_rank_start_on_first_page(self, data: dict) -> dict: """Reset rank_start to 1 if this is a first page (no before/after).""" if not (data.get("before") or data.get("after")): data["rank_start"] = 1 return data
class TopicListingSchema(PaginatedListingSchema): """Marshmallow schema to validate arguments for a topic listing page.""" period = ShortTimePeriod(allow_none=True) order = Enum(TopicSortOption, missing=None) tag = Ltree(missing=None) unfiltered = Boolean(missing=False) rank_start = Integer(data_key="n", validate=Range(min=1), missing=None) @pre_load def reset_rank_start_on_first_page( self, data: dict, many: bool, partial: Any ) -> dict: """Reset rank_start to 1 if this is a first page (no before/after).""" # pylint: disable=unused-argument if "rank_start" not in self.fields: return data if not (data.get("before") or data.get("after")): data["n"] = 1 return data
# doing an atomic decrement on request.user.invite_codes_remaining is going to make # it unusable as an integer in the template, so store the expected value after the # decrement first, to be able to use that instead num_remaining = request.user.invite_codes_remaining - 1 request.user.invite_codes_remaining = User.invite_codes_remaining - 1 return {"code": code, "num_remaining": num_remaining} @ic_view_config( route_name="user_default_listing_options", request_method="PUT", permission="edit_default_listing_options", ) @use_kwargs( {"order": Enum(TopicSortOption), "period": ShortTimePeriod(allow_none=True)} ) def put_default_listing_options( request: Request, order: TopicSortOption, period: Optional[ShortTimePeriod] ) -> dict: """Set the user's default listing options.""" user = request.context user.home_default_order = order if period: user.home_default_period = period.as_short_form() else: user.home_default_period = "all" return IC_NOOP
synchronize_session=False) # manually commit the transaction so triggers will execute request.tm.commit() # re-query the group to get complete data group = (request.query(Group).join_all_relationships().filter_by( group_id=group.group_id).one()) return {"group": group} @ic_view_config(route_name="group_user_settings", request_method="PATCH") @use_kwargs({ "order": Enum(TopicSortOption), "period": ShortTimePeriod(allow_none=True) }) def patch_group_user_settings(request: Request, order: TopicSortOption, period: Optional[ShortTimePeriod]) -> dict: """Set the user's default listing options.""" if period: default_period = period.as_short_form() else: default_period = "all" statement = (insert(UserGroupSettings.__table__).values( user_id=request.user.user_id, group_id=request.context.group_id, default_order=order, default_period=default_period, ).on_conflict_do_update(
request.tm.commit() # re-query the group to get complete data group = (request.query(Group).join_all_relationships().filter_by( group_id=group.group_id).one()) return {'group': group} @ic_view_config( route_name='group_user_settings', request_method='PATCH', ) @use_kwargs({ 'order': Enum(TopicSortOption), 'period': ShortTimePeriod(allow_none=True), }) def patch_group_user_settings( request: Request, order: TopicSortOption, period: Optional[ShortTimePeriod], ) -> dict: """Set the user's default listing options.""" if period: default_period = period.as_short_form() else: default_period = 'all' statement = (insert(UserGroupSettings.__table__).values( user_id=request.user.user_id, group_id=request.context.group_id,
# decrement first, to be able to use that instead num_remaining = request.user.invite_codes_remaining - 1 request.user.invite_codes_remaining = User.invite_codes_remaining - 1 return {"code": code, "num_remaining": num_remaining} @ic_view_config( route_name="user_default_listing_options", request_method="PUT", permission="edit_default_listing_options", ) @use_kwargs( { "order": Enum(TopicSortOption), "period": ShortTimePeriod(allow_none=True, missing=None), }, locations=( "form", ), # will crash due to trying to find JSON data without this ) def put_default_listing_options(request: Request, order: TopicSortOption, period: Optional[SimpleHoursPeriod]) -> dict: """Set the user's default listing options.""" user = request.context user.home_default_order = order if period: user.home_default_period = period.as_short_form() else: user.home_default_period = "all"