From 37f858c2778eea4f5ee9a552cca3f0f76bae9de1 Mon Sep 17 00:00:00 2001 From: Ernesto Rico Schmidt <ernesto@helsinki.at> Date: Mon, 14 Nov 2022 18:15:55 -0400 Subject: [PATCH] Avoid IndexError exception Only return the next repetition timeslot if there is one Fixes #131 --- poetry.lock | 38 ++++++++++++++--------------- program/views.py | 63 ++++++++++++++++-------------------------------- 2 files changed, 40 insertions(+), 61 deletions(-) diff --git a/poetry.lock b/poetry.lock index 0148ba0c..c7b4ed59 100644 --- a/poetry.lock +++ b/poetry.lock @@ -229,7 +229,7 @@ sidecar = ["drf-spectacular-sidecar"] [[package]] name = "exceptiongroup" -version = "1.0.0" +version = "1.0.3" description = "Backport of PEP 654 (exception groups)" category = "dev" optional = false @@ -393,7 +393,7 @@ pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" [[package]] name = "pathspec" -version = "0.10.1" +version = "0.10.2" description = "Utility library for gitignore style pattern matching of file paths." category = "dev" optional = false @@ -413,15 +413,15 @@ tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "pa [[package]] name = "platformdirs" -version = "2.5.2" -description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +version = "2.5.4" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false python-versions = ">=3.7" [package.extras] -docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx (>=4)", "sphinx-autodoc-typehints (>=1.12)"] -test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] +docs = ["furo (>=2022.9.29)", "proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.4)"] +test = ["appdirs (==1.4.4)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] [[package]] name = "pluggy" @@ -648,7 +648,7 @@ use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "setuptools" -version = "65.5.0" +version = "65.5.1" description = "Easily download, build, install, upgrade, and uninstall Python packages" category = "main" optional = false @@ -656,7 +656,7 @@ python-versions = ">=3.7" [package.extras] docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mock", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] [[package]] @@ -714,7 +714,7 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] name = "virtualenv" -version = "20.16.6" +version = "20.16.7" description = "Virtual Python Environment builder" category = "dev" optional = false @@ -830,8 +830,8 @@ drf-spectacular = [ {file = "drf_spectacular-0.24.2-py3-none-any.whl", hash = "sha256:b276e6f7bda6dfb911e742dab87c6e97bc67da2dafe82d6fd8df7cec6c8b03ec"}, ] exceptiongroup = [ - {file = "exceptiongroup-1.0.0-py3-none-any.whl", hash = "sha256:2ac84b496be68464a2da60da518af3785fff8b7ec0d090a581604bc870bdee41"}, - {file = "exceptiongroup-1.0.0.tar.gz", hash = "sha256:affbabf13fb6e98988c38d9c5650e701569fe3c1de3233cfb61c5f33774690ad"}, + {file = "exceptiongroup-1.0.3-py3-none-any.whl", hash = "sha256:6002703c7d31fb9950ddc8780840f67880c440895dc1151dd551553aa1246e4a"}, + {file = "exceptiongroup-1.0.3.tar.gz", hash = "sha256:76cac74b5207c5997678a1c7105cb6f14213c9c63c096a38cfcb529d83ce5c02"}, ] filelock = [ {file = "filelock-3.8.0-py3-none-any.whl", hash = "sha256:617eb4e5eedc82fc5f47b6d61e4d11cb837c56cb4544e39081099fa17ad109d4"}, @@ -889,8 +889,8 @@ packaging = [ {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, ] pathspec = [ - {file = "pathspec-0.10.1-py3-none-any.whl", hash = "sha256:46846318467efc4556ccfd27816e004270a9eeeeb4d062ce5e6fc7a87c573f93"}, - {file = "pathspec-0.10.1.tar.gz", hash = "sha256:7ace6161b621d31e7902eb6b5ae148d12cfd23f4a249b9ffb6b9fee12084323d"}, + {file = "pathspec-0.10.2-py3-none-any.whl", hash = "sha256:88c2606f2c1e818b978540f73ecc908e13999c6c3a383daf3705652ae79807a5"}, + {file = "pathspec-0.10.2.tar.gz", hash = "sha256:8f6bf73e5758fd365ef5d58ce09ac7c27d2833a8d7da51712eac6e27e35141b0"}, ] Pillow = [ {file = "Pillow-9.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:0b7257127d646ff8676ec8a15520013a698d1fdc48bc2a79ba4e53df792526f2"}, @@ -954,8 +954,8 @@ Pillow = [ {file = "Pillow-9.3.0.tar.gz", hash = "sha256:c935a22a557a560108d780f9a0fc426dd7459940dc54faa49d83249c8d3e760f"}, ] platformdirs = [ - {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, - {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"}, + {file = "platformdirs-2.5.4-py3-none-any.whl", hash = "sha256:af0276409f9a02373d540bf8480021a048711d572745aef4b7842dad245eba10"}, + {file = "platformdirs-2.5.4.tar.gz", hash = "sha256:1006647646d80f16130f052404c6b901e80ee4ed6bef6792e1f238a8969106f7"}, ] pluggy = [ {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, @@ -1189,8 +1189,8 @@ requests = [ {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"}, ] setuptools = [ - {file = "setuptools-65.5.0-py3-none-any.whl", hash = "sha256:f62ea9da9ed6289bfe868cd6845968a2c854d1427f8548d52cae02a42b4f0356"}, - {file = "setuptools-65.5.0.tar.gz", hash = "sha256:512e5536220e38146176efb833d4a62aa726b7bbff82cfbc8ba9eaa3996e0b17"}, + {file = "setuptools-65.5.1-py3-none-any.whl", hash = "sha256:d0b9a8433464d5800cbe05094acf5c6d52a91bfac9b52bcfc4d41382be5d5d31"}, + {file = "setuptools-65.5.1.tar.gz", hash = "sha256:e197a19aa8ec9722928f2206f8de752def0e4c9fc6953527360d1c36d94ddb2f"}, ] six = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, @@ -1217,6 +1217,6 @@ urllib3 = [ {file = "urllib3-1.26.12.tar.gz", hash = "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e"}, ] virtualenv = [ - {file = "virtualenv-20.16.6-py3-none-any.whl", hash = "sha256:186ca84254abcbde98180fd17092f9628c5fe742273c02724972a1d8a2035108"}, - {file = "virtualenv-20.16.6.tar.gz", hash = "sha256:530b850b523c6449406dfba859d6345e48ef19b8439606c5d74d7d3c9e14d76e"}, + {file = "virtualenv-20.16.7-py3-none-any.whl", hash = "sha256:efd66b00386fdb7dbe4822d172303f40cd05e50e01740b19ea42425cbe653e29"}, + {file = "virtualenv-20.16.7.tar.gz", hash = "sha256:8691e3ff9387f743e00f6bb20f70121f5e4f596cae754531f2b3b3a1b1ac696e"}, ] diff --git a/program/views.py b/program/views.py index acd66207..d442fb40 100644 --- a/program/views.py +++ b/program/views.py @@ -81,14 +81,10 @@ def json_day_schedule(request, year=None, month=None, day=None): if year is None and month is None and day is None: today = timezone.make_aware(datetime.combine(timezone.now(), time(0, 0))) else: - today = timezone.make_aware( - datetime.combine(date(year, month, day), time(0, 0)) - ) + today = timezone.make_aware(datetime.combine(date(year, month, day), time(0, 0))) timeslots = ( - TimeSlot.objects.get_24h_timeslots(today) - .select_related("schedule") - .select_related("show") + TimeSlot.objects.get_24h_timeslots(today).select_related("schedule").select_related("show") ) schedule = [] for ts in timeslots: @@ -317,9 +313,7 @@ class APIShowViewSet(DisabledObjectPermissionCheckMixin, viewsets.ModelViewSet): return Response(status=status.HTTP_401_UNAUTHORIZED) show = self.get_object() - serializer = ShowSerializer( - show, data=request.data, context={"user": request.user} - ) + serializer = ShowSerializer(show, data=request.data, context={"user": request.user}) if serializer.is_valid(): # Common users mustn't edit the show's name @@ -513,9 +507,7 @@ class APIScheduleViewSet( schedule = self.get_object() # If default playlist id or repetition are given, just update - if default_playlist_id := request.data.get("schedule").get( - "default_playlist_id" - ): + if default_playlist_id := request.data.get("schedule").get("default_playlist_id"): schedule.default_playlist_id = int(default_playlist_id) schedule.save() @@ -530,9 +522,7 @@ class APIScheduleViewSet( return Response(serializer.data) try: - resolution = Schedule.resolve_conflicts( - request.data, schedule.pk, schedule.show.pk - ) + resolution = Schedule.resolve_conflicts(request.data, schedule.pk, schedule.show.pk) except ScheduleConflictError as exc: return Response(exc.conflicts, status.HTTP_409_CONFLICT) @@ -592,9 +582,8 @@ class APITimeSlotViewSet( def update(self, request, *args, **kwargs): show_pk = get_values(self.kwargs, "show_pk") - if ( - not request.user.is_superuser - and show_pk not in request.user.shows.values_lis("id", flat=True) + if not request.user.is_superuser and show_pk not in request.user.shows.values_lis( + "id", flat=True ): return Response(status=status.HTTP_401_UNAUTHORIZED) @@ -606,9 +595,10 @@ class APITimeSlotViewSet( # Return the next repetition # We do this because the Dashboard needs to update the repetition timeslot as well # but with another playlist containing the recording instead of the original playlist - ts = TimeSlot.objects.filter(show=show_pk, start__gt=timeslot.start)[0] - if ts.is_repetition: - serializer = TimeSlotSerializer(ts) + if first_repetition := TimeSlot.objects.filter( + show=show_pk, start__gt=timeslot.start, is_repetition=True + ).first(): + serializer = TimeSlotSerializer(first_repetition) return Response(serializer.data) # ...or nothing if there isn't one @@ -662,9 +652,8 @@ class APINoteViewSet( """ show_pk, timeslot_pk = get_values(self.kwargs, "show_pk", "timeslot_pk") - if ( - not request.user.is_superuser - and show_pk not in request.user.shows.values_list("id", flat=True) + if not request.user.is_superuser and show_pk not in request.user.shows.values_list( + "id", flat=True ): return Response(status=status.HTTP_401_UNAUTHORIZED) @@ -674,9 +663,7 @@ class APINoteViewSet( ) if serializer.is_valid(): - hosts = Host.objects.filter( - shows__in=request.user.shows.values_list("id", flat=True) - ) + hosts = Host.objects.filter(shows__in=request.user.shows.values_list("id", flat=True)) if not request.user.is_superuser and request.data["host"] not in hosts: serializer.validated_data["host"] = None @@ -691,9 +678,8 @@ class APINoteViewSet( """ show_pk = get_values(self.kwargs, "show_pk") - if ( - not request.user.is_superuser - and show_pk not in request.user.shows.values_list("id", flat=True) + if not request.user.is_superuser and show_pk not in request.user.shows.values_list( + "id", flat=True ): return Response(status=status.HTTP_401_UNAUTHORIZED) @@ -701,14 +687,10 @@ class APINoteViewSet( serializer = NoteSerializer(note, data=request.data) if serializer.is_valid(): - hosts = Host.objects.filter( - shows__in=request.user.shows.values_list("id", flat=True) - ) + hosts = Host.objects.filter(shows__in=request.user.shows.values_list("id", flat=True)) # Don't assign a host the user mustn't edit. Reassign the original value instead if not request.user.is_superuser and int(request.data["host"]) not in hosts: - serializer.validated_data["host"] = Host.objects.filter( - pk=note.host_id - )[0] + serializer.validated_data["host"] = Host.objects.filter(pk=note.host_id)[0] serializer.save() return Response(serializer.data) @@ -721,9 +703,8 @@ class APINoteViewSet( """ show_pk = get_values(self.kwargs, "show_pk") - if ( - not request.user.is_superuser - and show_pk not in request.user.shows.values_list("id", flat=True) + if not request.user.is_superuser and show_pk not in request.user.shows.values_list( + "id", flat=True ): return Response(status=status.HTTP_401_UNAUTHORIZED) @@ -792,9 +773,7 @@ class APIMusicFocusViewSet(ActiveFilterMixin, viewsets.ModelViewSet): create=extend_schema(summary="Create a new funding category."), retrieve=extend_schema(summary="Retrieve a single funding category."), update=extend_schema(summary="Update an existing funding category."), - partial_update=extend_schema( - summary="Partially update an existing funding category." - ), + partial_update=extend_schema(summary="Partially update an existing funding category."), destroy=extend_schema(summary="Delete an existing funding category."), list=extend_schema(summary="List all funding categories."), ) -- GitLab