Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add type safety and type hinting #317

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
Prev Previous commit
Next Next commit
🧹 clean up type aliases
  • Loading branch information
ashleyzhang01 committed Nov 14, 2024
commit c0bffdb7bb3eb880fb063abd12982bc4f97a37aa
13 changes: 4 additions & 9 deletions backend/penndata/views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import datetime
from datetime import timedelta
from typing import Any, Optional, Sequence, TypeAlias, cast
from typing import Any, Optional, Sequence, cast

import requests
from bs4 import BeautifulSoup
@@ -32,11 +32,6 @@
from utils.types import get_user


CalendarEventList: TypeAlias = QuerySet[CalendarEvent, Manager[CalendarEvent]]
EventList: TypeAlias = QuerySet[Event, Manager[Event]]
HomePageOrderList: TypeAlias = QuerySet[HomePageOrder, Manager[HomePageOrder]]


class News(APIView):
"""
GET: Get's news article from the DP
@@ -104,7 +99,7 @@
permission_classes = [AllowAny]
serializer_class = CalendarEventSerializer

def get_queryset(self) -> CalendarEventList:
def get_queryset(self) -> QuerySet[CalendarEvent, Manager[CalendarEvent]]:
return CalendarEvent.objects.filter(
date_obj__gte=timezone.localtime(),
date_obj__lte=timezone.localtime() + timedelta(days=30),
@@ -120,7 +115,7 @@
permission_classes = [AllowAny]
serializer_class = EventSerializer

def get_queryset(self) -> EventList:
def get_queryset(self) -> QuerySet[Event, Manager[Event]]:
queryset = Event.objects.all()

event_type = self.kwargs.get("type")
@@ -148,7 +143,7 @@
permission_classes = [AllowAny]
serializer_class = HomePageOrderSerializer

def get_queryset(self) -> HomePageOrderList:
def get_queryset(self) -> QuerySet[HomePageOrder, Manager[HomePageOrder]]:
return HomePageOrder.objects.all()


@@ -322,7 +317,7 @@
if date == timezone.localtime().date():
# Set value to None if the last retrieved data was
# over 2 hours old to avoid extrapolation
if before_date and hour_date - datetime.timedelta(hours=1) > before_date:

Check warning on line 320 in backend/penndata/views.py

Codecov / codecov/patch

backend/penndata/views.py#L320

Added line #L320 was not covered by tests
for i in range(hour, 24):
usage[i] = None
break
16 changes: 5 additions & 11 deletions backend/portal/views.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, List, Optional, TypeAlias
from typing import Any, List, Optional

from django.db.models import Count, Manager, Q, QuerySet
from django.db.models.functions import Trunc
@@ -38,12 +38,6 @@
from utils.types import AuthRequest, get_auth_user


PollQuerySet: TypeAlias = QuerySet[Poll, Manager[Poll]]
PostQuerySet: TypeAlias = QuerySet[Post, Manager[Post]]
PollVoteQuerySet: TypeAlias = QuerySet[PollVote, Manager[PollVote]]
PollOptionQuerySet: TypeAlias = QuerySet[PollOption, Manager[PollOption]]


class UserInfo(APIView):
"""Returns User information"""

@@ -97,7 +91,7 @@ class Polls(viewsets.ModelViewSet[Poll]):
permission_classes = [PollOwnerPermission | IsSuperUser]
serializer_class = PollSerializer

def get_queryset(self) -> PollQuerySet:
def get_queryset(self) -> QuerySet[Poll, Manager[Poll]]:
# all polls if superuser, polls corresponding to club for regular user
user = get_auth_user(self.request)
return (
@@ -193,7 +187,7 @@ class PollOptions(viewsets.ModelViewSet[PollOption]):
permission_classes = [OptionOwnerPermission | IsSuperUser]
serializer_class = PollOptionSerializer

def get_queryset(self) -> PollOptionQuerySet:
def get_queryset(self) -> QuerySet[PollOption, Manager[PollOption]]:
# if user is admin, they can update anything
# if user is not admin, they can only update their own options
user = get_auth_user(self.request)
@@ -217,7 +211,7 @@ class PollVotes(viewsets.ModelViewSet[PollVote]):
permission_classes = [PollOwnerPermission | IsSuperUser]
serializer_class = PollVoteSerializer

def get_queryset(self) -> PollVoteQuerySet:
def get_queryset(self) -> QuerySet[PollVote, Manager[PollVote]]:
return PollVote.objects.none()

@action(detail=False, methods=["post"])
@@ -284,7 +278,7 @@ class Posts(viewsets.ModelViewSet[Post]):
permission_classes = [PostOwnerPermission | IsSuperUser]
serializer_class = PostSerializer

def get_queryset(self) -> PostQuerySet:
def get_queryset(self) -> QuerySet[Post, Manager[Post]]:
user = get_auth_user(self.request)
return (
Post.objects.all()
25 changes: 10 additions & 15 deletions backend/sublet/views.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Type, TypeAlias, cast
from typing import Any, Type, cast

from django.db.models import Manager, QuerySet, prefetch_related_objects
from django.http import QueryDict
@@ -32,13 +32,6 @@
from utils.types import get_user


SubletQuerySet: TypeAlias = QuerySet[Sublet, Manager[Sublet]]
OfferQuerySet: TypeAlias = QuerySet[Offer, Manager[Offer]]
AmenityQuerySet: TypeAlias = QuerySet[Amenity, Manager[Amenity]]
ImageList: TypeAlias = QuerySet[SubletImage, Manager[SubletImage]]
UserOfferQuerySet: TypeAlias = QuerySet[Offer, Manager[Offer]]


class Amenities(generics.ListAPIView):
serializer_class = AmenitySerializer
queryset = Amenity.objects.all()
@@ -52,15 +45,15 @@
serializer_class = SubletSerializerSimple
permission_classes = [IsAuthenticated]

def get_queryset(self) -> SubletQuerySet:
def get_queryset(self) -> QuerySet[Sublet, Manager[Sublet]]:
return get_user(self.request).sublets_favorited


class UserOffers(generics.ListAPIView):
serializer_class = OfferSerializer
permission_classes = [IsAuthenticated]

def get_queryset(self) -> UserOfferQuerySet:
def get_queryset(self) -> QuerySet[Offer, Manager[Offer]]:
return Offer.objects.filter(user=get_user(self.request))


@@ -84,7 +77,7 @@
def get_serializer_class(self) -> Type[BaseModelSerializer]:
return SubletSerializerRead if self.action == "retrieve" else SubletSerializer

def get_queryset(self) -> SubletQuerySet:
def get_queryset(self) -> QuerySet[Sublet, Manager[Sublet]]:
return Sublet.objects.all()

def create(self, request: Request, *args: Any, **kwargs: Any) -> Response:
@@ -137,10 +130,10 @@
"""Returns a list of Sublets that match query parameters and user ownership."""
# Get query parameters from request (e.g., amenities, user_owned)
params = request.query_params
queryset: SubletQuerySet = self.get_queryset()
queryset: QuerySet[Sublet, Manager[Sublet]] = self.get_queryset()

if params.get("subletter", "false").lower() == "true":
queryset = queryset.filter(subletter=get_user(request))

Check warning on line 136 in backend/sublet/views.py

Codecov / codecov/patch

backend/sublet/views.py#L136

Added line #L136 was not covered by tests
else:
queryset = queryset.filter(expires_at__gte=timezone.now())

@@ -149,26 +142,26 @@
if parsed_date := parse_date(end_before):
date_filters["end_date__lte"] = parsed_date
if end_after := params.get("ends_after"):
if parsed_date := parse_date(end_after):
date_filters["end_date__gte"] = parsed_date

Check warning on line 146 in backend/sublet/views.py

Codecov / codecov/patch

backend/sublet/views.py#L145-L146

Added lines #L145 - L146 were not covered by tests
if starts_before := params.get("starts_before"):
if parsed_date := parse_date(starts_before):
date_filters["start_date__lte"] = parsed_date

Check warning on line 149 in backend/sublet/views.py

Codecov / codecov/patch

backend/sublet/views.py#L148-L149

Added lines #L148 - L149 were not covered by tests
if starts_after := params.get("starts_after"):
if parsed_date := parse_date(starts_after):
date_filters["start_date__gte"] = parsed_date

Check warning on line 152 in backend/sublet/views.py

Codecov / codecov/patch

backend/sublet/views.py#L151-L152

Added lines #L151 - L152 were not covered by tests

numeric_filters = {}
if min_price := params.get("min_price"):
try:
numeric_filters["price__gte"] = int(min_price)
except ValueError:
pass

Check warning on line 159 in backend/sublet/views.py

Codecov / codecov/patch

backend/sublet/views.py#L158-L159

Added lines #L158 - L159 were not covered by tests
if max_price := params.get("max_price"):
try:
numeric_filters["price__lte"] = int(max_price)
except ValueError:
pass

Check warning on line 164 in backend/sublet/views.py

Codecov / codecov/patch

backend/sublet/views.py#L163-L164

Added lines #L163 - L164 were not covered by tests

basic_filters = {
"title__icontains": params.get("title"),
@@ -198,7 +191,9 @@
permission_classes = [SubletImageOwnerPermission | IsSuperUser]
parser_classes = (MultiPartParser, FormParser)

def get_queryset(self, *args: Any, **kwargs: Any) -> ImageList:
def get_queryset(
self, *args: Any, **kwargs: Any
) -> QuerySet[SubletImage, Manager[SubletImage]]:
sublet = get_object_or_404(Sublet, id=int(self.kwargs["sublet_id"]))
return SubletImage.objects.filter(sublet=sublet)

@@ -241,7 +236,7 @@
http_method_names = ["post", "delete"]
permission_classes = [IsAuthenticated | IsSuperUser]

def get_queryset(self) -> SubletQuerySet:
def get_queryset(self) -> QuerySet[Sublet, Manager[Sublet]]:
user = get_user(self.request)
return user.sublets_favorited

@@ -279,7 +274,7 @@
permission_classes = [OfferOwnerPermission | IsSuperUser]
serializer_class = OfferSerializer

def get_queryset(self) -> OfferQuerySet:
def get_queryset(self) -> QuerySet[Offer, Manager[Offer]]:
return Offer.objects.filter(sublet_id=int(self.kwargs["sublet_id"])).order_by(
"created_date"
)
Loading