diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4b72ee80a7..6a9a67fb8d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,13 +3,37 @@ default_stages: [commit] fail_fast: true repos: -- repo: https://github.com/pre-commit/pre-commit-hooks + - repo: https://github.com/pre-commit/pre-commit-hooks rev: master hooks: - id: trailing-whitespace files: (^|/)a/.+\.(py|html|sh|css|js)$ + - id: check-merge-conflict + name: check for merge conflict + description: Prevent accidentally commiting files with merge conflicts. + - id: end-of-file-fixer + name: fix end of files. + description: Ensures that a file is either empty, or ends with one newline. -- repo: local + + - repo: https://github.com/asottile/seed-isort-config + rev: v2.1.0 + hooks: + - id: seed-isort-config + + - repo: https://github.com/pre-commit/mirrors-isort + rev: v4.3.21 + hooks: + - id: isort + + - repo: https://github.com/ambv/black + rev: stable + hooks: + - id: black + args: [--line-length=120, --safe] + language_version: python3.7 + + - repo: local hooks: - id: flake8 name: flake8 @@ -18,3 +42,10 @@ repos: types: [python] args: ['--config=setup.cfg'] + - id: pre-commit-django-migrations + name: Check django migrations + entry: python manage.py makemigrations --check + language: system + types: [python] + pass_filenames: false + require_serial: true diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 8b13789179..e69de29bb2 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -1 +0,0 @@ - diff --git a/LICENSE b/LICENSE index b530761658..9a62c4cb53 100644 --- a/LICENSE +++ b/LICENSE @@ -7,4 +7,3 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - diff --git a/Procfile b/Procfile index a0d05538e4..6b2fde1d76 100644 --- a/Procfile +++ b/Procfile @@ -1,3 +1,2 @@ web: gunicorn config.wsgi:application release: python manage.py collectstatic --noinput && python manage.py migrate - diff --git a/care/__init__.py b/care/__init__.py index e1d861523a..eed836dad7 100644 --- a/care/__init__.py +++ b/care/__init__.py @@ -1,7 +1,2 @@ __version__ = "0.1.0" -__version_info__ = tuple( - [ - int(num) if num.isdigit() else num - for num in __version__.replace("-", ".", 1).split(".") - ] -) +__version_info__ = tuple([int(num) if num.isdigit() else num for num in __version__.replace("-", ".", 1).split(".")]) diff --git a/care/facility/admin.py b/care/facility/admin.py index 8931fb8448..7541c198cd 100644 --- a/care/facility/admin.py +++ b/care/facility/admin.py @@ -1,18 +1,19 @@ from django.contrib import admin from .models import ( + Ambulance, + AmbulanceDriver, + Building, Facility, - FacilityStaff, FacilityCapacity, + FacilityStaff, FacilityVolunteer, - Building, - Room, - StaffRoomAllocation, - InventoryItem, Inventory, + InventoryItem, InventoryLog, - AmbulanceDriver, - Ambulance) + Room, + StaffRoomAllocation, +) class BuildingAdmin(admin.ModelAdmin): @@ -59,11 +60,13 @@ class AmbulanceDriverInline(admin.TabularInline): class AmbulanceAdmin(admin.ModelAdmin): search_fields = ["vehicle_number"] - inlines = [AmbulanceDriverInline, ] + inlines = [ + AmbulanceDriverInline, + ] class AmbulanceDriverAdmin(admin.ModelAdmin): - autocomplete_fields = ['ambulance'] + autocomplete_fields = ["ambulance"] admin.site.register(Facility, FacilityAdmin) diff --git a/care/facility/api/serializers.py b/care/facility/api/serializers.py index 0e50212a45..4a54fd0714 100644 --- a/care/facility/api/serializers.py +++ b/care/facility/api/serializers.py @@ -3,13 +3,16 @@ from drf_extra_fields.geo_fields import PointField from rest_framework import serializers -from care.facility.models import FACILITY_TYPES, AmbulanceDriver -from care.facility.models import Facility, Ambulance +from care.facility.models import FACILITY_TYPES, Ambulance, AmbulanceDriver, Facility from config.serializers import ChoiceField User = get_user_model() -TIMESTAMP_FIELDS = ('created_date', 'modified_date', 'deleted',) +TIMESTAMP_FIELDS = ( + "created_date", + "modified_date", + "deleted", +) class FacilitySerializer(serializers.ModelSerializer): @@ -40,12 +43,11 @@ class Meta: class AmbulanceDriverSerializer(serializers.ModelSerializer): class Meta: model = AmbulanceDriver - exclude = TIMESTAMP_FIELDS + ('ambulance',) + exclude = TIMESTAMP_FIELDS + ("ambulance",) class AmbulanceSerializer(serializers.ModelSerializer): - drivers = serializers.ListSerializer( - child=AmbulanceDriverSerializer()) + drivers = serializers.ListSerializer(child=AmbulanceDriverSerializer()) class Meta: model = Ambulance @@ -53,14 +55,14 @@ class Meta: def create(self, validated_data): with transaction.atomic(): - drivers = validated_data.pop('drivers', []) + drivers = validated_data.pop("drivers", []) ambulance = super(AmbulanceSerializer, self).create(validated_data) for d in drivers: - d['ambulance'] = ambulance + d["ambulance"] = ambulance AmbulanceDriverSerializer().create(d) return ambulance def update(self, instance, validated_data): - validated_data.pop('drivers', []) + validated_data.pop("drivers", []) ambulance = super(AmbulanceSerializer, self).update(instance, validated_data) return ambulance diff --git a/care/facility/api/views.py b/care/facility/api/views.py index 7e4854a341..cbf2309df6 100644 --- a/care/facility/api/views.py +++ b/care/facility/api/views.py @@ -1,22 +1,26 @@ from django_filters import rest_framework as filters -from rest_framework import status, serializers +from rest_framework import serializers, status from rest_framework.decorators import action from rest_framework.mixins import ( + CreateModelMixin, + DestroyModelMixin, ListModelMixin, RetrieveModelMixin, - CreateModelMixin, UpdateModelMixin, - DestroyModelMixin) +) from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from rest_framework.viewsets import GenericViewSet -from care.facility.api.serializers import FacilitySerializer, AmbulanceSerializer, AmbulanceDriverSerializer -from care.facility.models import Facility, Ambulance +from care.facility.api.serializers import ( + AmbulanceDriverSerializer, + AmbulanceSerializer, + FacilitySerializer, +) +from care.facility.models import Ambulance, Facility -class FacilityBaseViewset(CreateModelMixin, RetrieveModelMixin, - UpdateModelMixin, DestroyModelMixin, GenericViewSet): +class FacilityBaseViewset(CreateModelMixin, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, GenericViewSet): """Base class for all endpoints related to Faclity model.""" permission_classes = (IsAuthenticated,) @@ -42,7 +46,7 @@ def perform_update(self, serializer): class AmbulanceFilterSet(filters.FilterSet): - vehicle_numbers = filters.BaseInFilter(field_name='vehicle_number') + vehicle_numbers = filters.BaseInFilter(field_name="vehicle_number") class AmbulanceViewSet(FacilityBaseViewset, ListModelMixin): @@ -51,7 +55,7 @@ class AmbulanceViewSet(FacilityBaseViewset, ListModelMixin): filter_backends = (filters.DjangoFilterBackend,) filterset_class = AmbulanceFilterSet - @action(methods=['POST'], detail=True) + @action(methods=["POST"], detail=True) def add_driver(self, request): ambulance = self.get_object() serializer = AmbulanceDriverSerializer(data=request.data) @@ -60,7 +64,7 @@ def add_driver(self, request): driver = ambulance.ambulancedriver_set.create(**serializer.validated_data) return Response(data=AmbulanceDriverSerializer(driver).data, status=status.HTTP_201_CREATED) - @action(methods=['DELETE'], detail=True) + @action(methods=["DELETE"], detail=True) def remove_driver(self, request): class DeleteDriverSerializer(serializers.Serializer): driver_id = serializers.IntegerField() @@ -75,7 +79,7 @@ def create(self, validated_data): serializer = DeleteDriverSerializer(data=request.data) serializer.is_valid(raise_exception=True) - driver = ambulance.ambulancedriver_set.filter(id=serializer.validated_data['driver_id']).first() + driver = ambulance.ambulancedriver_set.filter(id=serializer.validated_data["driver_id"]).first() if not driver: raise serializers.ValidationError({"driver_id": "Detail not found"}) diff --git a/care/facility/forms.py b/care/facility/forms.py index a9648325dc..19925b7d54 100644 --- a/care/facility/forms.py +++ b/care/facility/forms.py @@ -7,17 +7,20 @@ class FacilityCreationForm(ModelForm): class Meta: model = Facility fields = ["name", "district", "address", "oxygen_capacity", "phone_number"] - labels = {"name": "Enter the name of your hospital", "district": "Pick your District", - "address": "Enter Hospital Address", - "phone_number": "Enter emergency contact number of your hospital","oxygen_capacity":"Enter the total oxygen capacity of your hospital (in litres)"} + labels = { + "name": "Enter the name of your hospital", + "district": "Pick your District", + "address": "Enter Hospital Address", + "phone_number": "Enter emergency contact number of your hospital", + "oxygen_capacity": "Enter the total oxygen capacity of your hospital (in litres)", + } class FacilityCapacityCreationForm(ModelForm): class Meta: model = FacilityCapacity fields = ["room_type", "total_capacity", "current_capacity"] - labels = {"room_type": "Bed Type", "total_capacity": "Total Capacity", - "current_capacity": "Currently Occupied"} + labels = {"room_type": "Bed Type", "total_capacity": "Total Capacity", "current_capacity": "Currently Occupied"} class DoctorsCountCreationForm(ModelForm): diff --git a/care/facility/models.py b/care/facility/models.py index b81d26ef7d..6abcfba9a4 100644 --- a/care/facility/models.py +++ b/care/facility/models.py @@ -1,6 +1,5 @@ from django.contrib.auth import get_user_model -from django.core.validators import MinValueValidator -from django.core.validators import RegexValidator +from django.core.validators import MinValueValidator, RegexValidator from django.db import models from location_field.models.spatial import LocationField @@ -34,7 +33,7 @@ def delete(self): ] phone_number_regex = RegexValidator( - regex="^((\+91|91|0)[\- ]{0,1})?[456789]\d{9}$", + regex=r"^((\+91|91|0)[\- ]{0,1})?[456789]\d{9}$", message="Please Enter 10/11 digit mobile number or landline as 0", code="invalid_mobile", ) @@ -50,9 +49,7 @@ class Facility(FacilityBaseModel): location = LocationField(based_fields=["address"], zoom=7, blank=True, null=True) oxygen_capacity = models.IntegerField() phone_number = models.CharField(max_length=14, validators=[phone_number_regex]) - created_by = models.ForeignKey( - User, on_delete=models.SET_NULL, null=True, blank=True - ) + created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True) def __str__(self): return self.name @@ -62,9 +59,7 @@ class Meta: class HospitalDoctors(FacilityBaseModel): - facility = models.ForeignKey( - "Facility", on_delete=models.CASCADE, null=False, blank=False - ) + facility = models.ForeignKey("Facility", on_delete=models.CASCADE, null=False, blank=False) area = models.IntegerField(choices=DOCTOR_TYPES) count = models.IntegerField() @@ -76,9 +71,7 @@ class Meta: class FacilityCapacity(FacilityBaseModel): - facility = models.ForeignKey( - "Facility", on_delete=models.CASCADE, null=False, blank=False - ) + facility = models.ForeignKey("Facility", on_delete=models.CASCADE, null=False, blank=False) room_type = models.IntegerField(choices=ROOM_TYPES) total_capacity = models.IntegerField(default=0, validators=[MinValueValidator(0)]) current_capacity = models.IntegerField(default=0, validators=[MinValueValidator(0)]) @@ -88,9 +81,7 @@ class Meta: class FacilityStaff(FacilityBaseModel): - facility = models.ForeignKey( - "Facility", on_delete=models.CASCADE, null=False, blank=False - ) + facility = models.ForeignKey("Facility", on_delete=models.CASCADE, null=False, blank=False) staff = models.ForeignKey(User, on_delete=models.CASCADE, null=False, blank=False) def __str__(self): @@ -98,12 +89,8 @@ def __str__(self): class FacilityVolunteer(FacilityBaseModel): - facility = models.ForeignKey( - "Facility", on_delete=models.CASCADE, null=False, blank=False - ) - volunteer = models.ForeignKey( - User, on_delete=models.CASCADE, null=False, blank=False - ) + facility = models.ForeignKey("Facility", on_delete=models.CASCADE, null=False, blank=False) + volunteer = models.ForeignKey(User, on_delete=models.CASCADE, null=False, blank=False) def __str__(self): return str(self.volunteer) + " for facility " + str(self.facility) @@ -116,9 +103,7 @@ def __str__(self): class Building(FacilityBaseModel): - facility = models.ForeignKey( - "Facility", on_delete=models.CASCADE, null=False, blank=False - ) + facility = models.ForeignKey("Facility", on_delete=models.CASCADE, null=False, blank=False) name = models.CharField(max_length=1000) num_rooms = models.IntegerField(validators=[MinValueValidator(0)], default=0) num_floors = models.IntegerField(validators=[MinValueValidator(0)], default=0) @@ -134,9 +119,7 @@ def __str__(self): class Room(FacilityBaseModel): - building = models.ForeignKey( - "Building", on_delete=models.CASCADE, null=False, blank=False - ) + building = models.ForeignKey("Building", on_delete=models.CASCADE, null=False, blank=False) num = models.CharField(max_length=1000) floor = models.IntegerField(validators=[MinValueValidator(0)], default=0) beds_capacity = models.IntegerField(validators=[MinValueValidator(0)], default=0) @@ -167,32 +150,16 @@ class InventoryItem(FacilityBaseModel): unit = models.CharField(max_length=20) def __str__(self): - return ( - self.name - + " with unit " - + self.unit - + " with minimum stock " - + str(self.minimum_stock) - ) + return self.name + " with unit " + self.unit + " with minimum stock " + str(self.minimum_stock) class Inventory(FacilityBaseModel): - facility = models.ForeignKey( - "Facility", on_delete=models.CASCADE, null=False, blank=False - ) + facility = models.ForeignKey("Facility", on_delete=models.CASCADE, null=False, blank=False) item = models.ForeignKey("InventoryItem", on_delete=models.CASCADE) quantitiy = models.IntegerField(validators=[MinValueValidator(0)], default=0) def __str__(self): - return ( - self.item.name - + " : " - + str(self.quantitiy) - + " " - + self.item.unit - + " in " - + str(self.facility) - ) + return self.item.name + " : " + str(self.quantitiy) + " " + self.item.unit + " in " + str(self.facility) class Meta: verbose_name_plural = "Inventories" @@ -200,9 +167,7 @@ class Meta: class InventoryLog(FacilityBaseModel): inventory = models.ForeignKey("Inventory", on_delete=models.CASCADE) - updated_by = models.ForeignKey( - User, on_delete=models.SET_NULL, null=True, blank=True - ) + updated_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True) prev_count = models.IntegerField(validators=[MinValueValidator(0)], default=0) new_count = models.IntegerField(validators=[MinValueValidator(0)], default=0) diff --git a/care/facility/urls.py b/care/facility/urls.py index f3b68c6295..10dcb21d81 100644 --- a/care/facility/urls.py +++ b/care/facility/urls.py @@ -1,14 +1,14 @@ from django.urls import path from .views import ( - FacilityCreation, - FacilityCapacityCreation, - FacilitiesView, - FacilityView, - FacilityUpdation, - FacilityCapacityUpdation, DoctorCountCreation, DoctorCountUpdation, + FacilitiesView, + FacilityCapacityCreation, + FacilityCapacityUpdation, + FacilityCreation, + FacilityUpdation, + FacilityView, ) app_name = "facility" @@ -17,24 +17,8 @@ path("", FacilitiesView.as_view(), name="facilities-view"), path("", FacilityView.as_view(), name="facility-view"), path("/update", FacilityUpdation.as_view(), name="facility-update"), - path( - "/capacity/add/", - FacilityCapacityCreation.as_view(), - name="facility-capacity-create", - ), - path( - "/capacity//", - FacilityCapacityUpdation.as_view(), - name="facility-capacity-update", - ), - path( - "/doctorcount/add/", - DoctorCountCreation.as_view(), - name="facility-doctor-count-create", - ), - path( - "/doctorcount//", - DoctorCountUpdation.as_view(), - name="facility-doctor-count-update", - ), + path("/capacity/add/", FacilityCapacityCreation.as_view(), name="facility-capacity-create",), + path("/capacity//", FacilityCapacityUpdation.as_view(), name="facility-capacity-update",), + path("/doctorcount/add/", DoctorCountCreation.as_view(), name="facility-doctor-count-create",), + path("/doctorcount//", DoctorCountUpdation.as_view(), name="facility-doctor-count-update",), ] diff --git a/care/facility/views.py b/care/facility/views.py index 6a31a90327..4467c7c72c 100644 --- a/care/facility/views.py +++ b/care/facility/views.py @@ -1,17 +1,17 @@ import logging -from django.shortcuts import render, redirect -from django.views import View -from django.http import HttpResponseRedirect -from django.db import IntegrityError +from django.conf import settings from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.views import redirect_to_login -from django.conf import settings +from django.db import IntegrityError +from django.http import HttpResponseRedirect +from django.shortcuts import redirect, render +from django.views import View from .forms import ( - FacilityCreationForm, - FacilityCapacityCreationForm, DoctorsCountCreationForm, + FacilityCapacityCreationForm, + FacilityCreationForm, ) from .models import Facility, FacilityCapacity, HospitalDoctors @@ -25,7 +25,6 @@ def dispatch(self, request, *args, **kwargs): class FacilitiesView(LoginRequiredMixin, StaffRequiredMixin, View): - template = "facility/facilities_view.html" def get(self, request): @@ -39,7 +38,6 @@ def get(self, request): class FacilityView(LoginRequiredMixin, StaffRequiredMixin, View): - template = "facility/facility_view.html" def get(self, request, pk): @@ -51,11 +49,7 @@ def get(self, request, pk): return render( request, self.template, - { - "capacities": capacities, - "doctor_counts": doctor_counts, - "facility": facility_obj, - }, + {"capacities": capacities, "doctor_counts": doctor_counts, "facility": facility_obj,}, ) except Exception as e: logging.error(e) @@ -63,7 +57,6 @@ def get(self, request, pk): class FacilityCreation(LoginRequiredMixin, StaffRequiredMixin, View): - form_class = FacilityCreationForm template = "facility/facility_creation.html" @@ -92,7 +85,6 @@ def post(self, request): class FacilityUpdation(LoginRequiredMixin, StaffRequiredMixin, View): - form_class = FacilityCreationForm template = "facility/facility_updation.html" @@ -130,9 +122,7 @@ def get(self, request, pk): form = self.form_class() current_user = request.user facility_obj = Facility.objects.get(id=pk, created_by=current_user) - return render( - request, self.template, {"form": form, "facility": facility_obj} - ) + return render(request, self.template, {"form": form, "facility": facility_obj}) except Exception as e: logging.error(e) return HttpResponseRedirect("/500") @@ -145,7 +135,7 @@ def post(self, request, pk): validation_error = False duplicate = False if form.is_valid(): - if form.cleaned_data.get('total_capacity') >= form.cleaned_data.get('current_capacity'): + if form.cleaned_data.get("total_capacity") >= form.cleaned_data.get("current_capacity"): duplicate = False facility_capacity_obj = form.save(commit=False) facility_obj = Facility.objects.get(id=pk) @@ -153,13 +143,9 @@ def post(self, request, pk): try: facility_capacity_obj.save() if "addmore" in data: - return redirect( - "facility:facility-capacity-create", facility_obj.id - ) + return redirect("facility:facility-capacity-create", facility_obj.id) else: - return redirect( - "facility:facility-doctor-count-create", facility_obj.id - ) + return redirect("facility:facility-doctor-count-create", facility_obj.id) except IntegrityError: duplicate = True else: @@ -184,9 +170,7 @@ def get(self, request, fpk, cpk): facility_obj = Facility.objects.get(id=fpk, created_by=current_user) capacity_obj = FacilityCapacity.objects.get(id=cpk, facility=facility_obj) form = self.form_class(instance=capacity_obj) - return render( - request, self.template, {"form": form, "facility": facility_obj} - ) + return render(request, self.template, {"form": form, "facility": facility_obj}) except Exception as e: logging.error(e) return HttpResponseRedirect("/500") @@ -201,7 +185,7 @@ def post(self, request, fpk, cpk): duplicate = False validation_error = False if form.is_valid(): - if form.cleaned_data.get('total_capacity') >= form.cleaned_data.get('current_capacity'): + if form.cleaned_data.get("total_capacity") >= form.cleaned_data.get("current_capacity"): try: form.save() return redirect("facility:facility-view", facility_obj.id) @@ -210,8 +194,9 @@ def post(self, request, fpk, cpk): else: validation_error = True return render( - request, self.template, {"form": form, "duplicate": duplicate, - "validation_error": validation_error, "facility": facility_obj} + request, + self.template, + {"form": form, "duplicate": duplicate, "validation_error": validation_error, "facility": facility_obj}, ) except Exception as e: logging.error(e) @@ -227,9 +212,7 @@ def get(self, request, pk): form = self.form_class() current_user = request.user facility_obj = Facility.objects.get(id=pk, created_by=current_user) - return render( - request, self.template, {"form": form, "facility": facility_obj} - ) + return render(request, self.template, {"form": form, "facility": facility_obj}) except Exception as e: logging.error(e) return HttpResponseRedirect("/500") @@ -246,18 +229,12 @@ def post(self, request, pk): try: facility_capacity_obj.save() if "addmore" in data: - return redirect( - "facility:facility-doctor-count-create", facility_obj.id - ) + return redirect("facility:facility-doctor-count-create", facility_obj.id) else: return redirect("facility:facility-view", facility_obj.id) except IntegrityError: duplicate = True - return render( - request, - self.template, - {"form": form, "facility": facility_obj, "duplicate": duplicate}, - ) + return render(request, self.template, {"form": form, "facility": facility_obj, "duplicate": duplicate},) except Exception as e: logging.error(e) return HttpResponseRedirect("/500") @@ -271,13 +248,9 @@ def get(self, request, fpk, cpk): try: current_user = request.user facility_obj = Facility.objects.get(id=fpk, created_by=current_user) - doctor_count_obj = HospitalDoctors.objects.get( - id=cpk, facility=facility_obj - ) + doctor_count_obj = HospitalDoctors.objects.get(id=cpk, facility=facility_obj) form = self.form_class(instance=doctor_count_obj) - return render( - request, self.template, {"form": form, "facility": facility_obj} - ) + return render(request, self.template, {"form": form, "facility": facility_obj}) except Exception as e: logging.error(e) return HttpResponseRedirect("/500") @@ -287,9 +260,7 @@ def post(self, request, fpk, cpk): data = request.POST current_user = request.user facility_obj = Facility.objects.get(id=fpk, created_by=current_user) - doctor_count_obj = HospitalDoctors.objects.get( - id=cpk, facility=facility_obj - ) + doctor_count_obj = HospitalDoctors.objects.get(id=cpk, facility=facility_obj) form = self.form_class(data, instance=doctor_count_obj) duplicate = False if form.is_valid(): @@ -298,9 +269,7 @@ def post(self, request, fpk, cpk): return redirect("facility:facility-view", facility_obj.id) except IntegrityError: duplicate = True - return render( - request, self.template, {"form": form, "duplicate": duplicate} - ) + return render(request, self.template, {"form": form, "duplicate": duplicate}) except Exception as e: logging.error(e) return HttpResponseRedirect("/500") diff --git a/care/static/css/custom.min.css b/care/static/css/custom.min.css index 25f82b2053..01b689dc53 100644 --- a/care/static/css/custom.min.css +++ b/care/static/css/custom.min.css @@ -1 +1 @@ -.bg-gray-100{background-color:#fbfafc}.btn-primary{background-color:#6025c0;color:#fff;box-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.06);background-image:linear-gradient(135deg,#6025c0,#4d1e9a)}.btn{display:inline-flex;align-items:center;justify-content:center;white-space:nowrap;font-weight:600;padding:.5rem 1rem;border-radius:.25rem;cursor:pointer}.care-secondary-color{color:#6025c0}label{margin-top:1rem;display:inline-block}.careblock{display:block!important}@media (min-width:768px){.cardwidth{width:30%!important;min-width:250px!important}} \ No newline at end of file +.bg-gray-100{background-color:#fbfafc}.btn-primary{background-color:#6025c0;color:#fff;box-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.06);background-image:linear-gradient(135deg,#6025c0,#4d1e9a)}.btn{display:inline-flex;align-items:center;justify-content:center;white-space:nowrap;font-weight:600;padding:.5rem 1rem;border-radius:.25rem;cursor:pointer}.care-secondary-color{color:#6025c0}label{margin-top:1rem;display:inline-block}.careblock{display:block!important}@media (min-width:768px){.cardwidth{width:30%!important;min-width:250px!important}} diff --git a/care/templates/500.html b/care/templates/500.html index 21df606657..46e43a9c37 100644 --- a/care/templates/500.html +++ b/care/templates/500.html @@ -9,5 +9,3 @@

Looks like something went wrong!

We track these errors automatically, but if the problem persists feel free to contact us. In the meantime, try refreshing.

{% endblock content %} - - diff --git a/care/templates/account/account_inactive.html b/care/templates/account/account_inactive.html index 17c21577a8..585b38c2ca 100644 --- a/care/templates/account/account_inactive.html +++ b/care/templates/account/account_inactive.html @@ -9,4 +9,3 @@

{% trans "Account Inactive" %}

{% trans "This account is inactive." %}

{% endblock %} - diff --git a/care/templates/account/email.html b/care/templates/account/email.html index 0dc8d145f9..b559811a19 100644 --- a/care/templates/account/email.html +++ b/care/templates/account/email.html @@ -77,4 +77,3 @@

{% trans "Add E-mail Address" %}

$('.form-group').removeClass('row'); {% endblock %} - diff --git a/care/templates/account/email_confirm.html b/care/templates/account/email_confirm.html index 46c7812636..2b0dd41f3e 100644 --- a/care/templates/account/email_confirm.html +++ b/care/templates/account/email_confirm.html @@ -29,4 +29,3 @@

{% trans "Confirm E-mail Address" %}

{% endif %} {% endblock %} - diff --git a/care/templates/account/logout.html b/care/templates/account/logout.html index 8e2e675480..52bcc7c979 100644 --- a/care/templates/account/logout.html +++ b/care/templates/account/logout.html @@ -19,4 +19,3 @@

{% trans "Sign Out" %}

{% endblock %} - diff --git a/care/templates/account/password_change.html b/care/templates/account/password_change.html index b72ca068bf..c96fcfdaa7 100644 --- a/care/templates/account/password_change.html +++ b/care/templates/account/password_change.html @@ -14,4 +14,3 @@

{% trans "Change Password" %}

{% endblock %} - diff --git a/care/templates/account/password_reset.html b/care/templates/account/password_reset.html index 845bbda735..31760ab95d 100644 --- a/care/templates/account/password_reset.html +++ b/care/templates/account/password_reset.html @@ -23,4 +23,3 @@

{% trans "Password Reset" %}

{% blocktrans %}Please contact us if you have any trouble resetting your password.{% endblocktrans %}

{% endblock %} - diff --git a/care/templates/account/password_reset_done.html b/care/templates/account/password_reset_done.html index c59534afcf..f2ff8e8cd1 100644 --- a/care/templates/account/password_reset_done.html +++ b/care/templates/account/password_reset_done.html @@ -14,4 +14,3 @@

{% trans "Password Reset" %}

{% blocktrans %}We have sent you an e-mail. Please contact us if you do not receive it within a few minutes.{% endblocktrans %}

{% endblock %} - diff --git a/care/templates/account/password_reset_from_key.html b/care/templates/account/password_reset_from_key.html index 4abdb56244..882540f70b 100644 --- a/care/templates/account/password_reset_from_key.html +++ b/care/templates/account/password_reset_from_key.html @@ -22,4 +22,3 @@

{% if token_fail %}{% trans "Bad Token" %}{% else %}{% trans "Change Passwor {% endif %} {% endif %} {% endblock %} - diff --git a/care/templates/account/password_reset_from_key_done.html b/care/templates/account/password_reset_from_key_done.html index 89be086f15..ebc8c254ab 100644 --- a/care/templates/account/password_reset_from_key_done.html +++ b/care/templates/account/password_reset_from_key_done.html @@ -7,4 +7,3 @@

{% trans "Change Password" %}

{% trans 'Your password is now changed.' %}

{% endblock %} - diff --git a/care/templates/account/password_set.html b/care/templates/account/password_set.html index 2232223517..6a45ece98e 100644 --- a/care/templates/account/password_set.html +++ b/care/templates/account/password_set.html @@ -14,4 +14,3 @@

{% trans "Set Password" %}

{% endblock %} - diff --git a/care/templates/account/signup_closed.html b/care/templates/account/signup_closed.html index 2322f176fb..ebcd845385 100644 --- a/care/templates/account/signup_closed.html +++ b/care/templates/account/signup_closed.html @@ -9,4 +9,3 @@

{% trans "Sign Up Closed" %}

{% trans "We are sorry, but the sign up is currently closed." %}

{% endblock %} - diff --git a/care/templates/account/verification_sent.html b/care/templates/account/verification_sent.html index ad093fd44c..d4fb9e93ce 100644 --- a/care/templates/account/verification_sent.html +++ b/care/templates/account/verification_sent.html @@ -10,4 +10,3 @@

{% trans "Verify Your E-mail Address" %}

{% blocktrans %}We have sent an e-mail to you for verification. Follow the link provided to finalize the signup process. Please contact us if you do not receive it within a few minutes.{% endblocktrans %}

{% endblock %} - diff --git a/care/templates/account/verified_email_required.html b/care/templates/account/verified_email_required.html index 09d4fde793..30eed9a47d 100644 --- a/care/templates/account/verified_email_required.html +++ b/care/templates/account/verified_email_required.html @@ -21,4 +21,3 @@

{% trans "Verify Your E-mail Address" %}

{% endblock %} - diff --git a/care/templates/users/user_detail.html b/care/templates/users/user_detail.html index e86eda1144..00122dc000 100644 --- a/care/templates/users/user_detail.html +++ b/care/templates/users/user_detail.html @@ -33,4 +33,3 @@

{{ object.username }}

{% endblock content %} - diff --git a/care/users/admin.py b/care/users/admin.py index e53cc3ba3f..1bb0ceef12 100644 --- a/care/users/admin.py +++ b/care/users/admin.py @@ -1,6 +1,7 @@ from django.contrib import admin from django.contrib.auth import admin as auth_admin from django.contrib.auth import get_user_model + from care.users.forms import UserChangeForm, UserCreationForm from care.users.models import Skill @@ -14,7 +15,7 @@ class UserAdmin(auth_admin.UserAdmin): add_form = UserCreationForm fieldsets = (("User", {"fields": ("user_type",)}),) + auth_admin.UserAdmin.fieldsets list_display = ["username", "is_superuser"] - search_fields = ['first_name', 'last_name'] + search_fields = ["first_name", "last_name"] admin.site.register(Skill) diff --git a/care/users/api/serializers.py b/care/users/api/serializers.py index 319e69abf8..0fc7012eca 100644 --- a/care/users/api/serializers.py +++ b/care/users/api/serializers.py @@ -30,5 +30,3 @@ class Meta: ) extra_kwargs = {"url": {"lookup_field": "username"}} - - diff --git a/care/users/api/views.py b/care/users/api/views.py index f338a20cb1..a6e158b1fd 100644 --- a/care/users/api/views.py +++ b/care/users/api/views.py @@ -1,12 +1,10 @@ from django.contrib.auth import get_user_model -from rest_framework import status +from rest_framework import status, viewsets from rest_framework.decorators import action +from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response -from rest_framework import viewsets -from rest_framework.permissions import IsAuthenticated, IsAdminUser - -from users.api.serializers import UserSerializer +from care.users.api.serializers import UserSerializer User = get_user_model() @@ -36,6 +34,5 @@ def get_queryset(self): @action(detail=False, methods=["GET"]) def getcurrentuser(self, request): return Response( - status=status.HTTP_200_OK, - data=self.serializer_class(request.user, context={"request": request}).data, + status=status.HTTP_200_OK, data=self.serializer_class(request.user, context={"request": request}).data, ) diff --git a/care/users/forms.py b/care/users/forms.py index 2c658bf6c3..339faac9b2 100644 --- a/care/users/forms.py +++ b/care/users/forms.py @@ -1,8 +1,8 @@ +from crispy_forms.helper import FormHelper +from crispy_forms.layout import Field, Layout from django.contrib.auth import forms, get_user_model from django.core.exceptions import ValidationError from django.utils.translation import ugettext_lazy as _ -from crispy_forms.helper import FormHelper -from crispy_forms.layout import Layout, Field User = get_user_model() @@ -63,17 +63,17 @@ def __init__(self, *args, **kwargs): super(CustomSignupForm, self).__init__(*args, **kwargs) self.helper = FormHelper() self.helper.layout = Layout( - Field('username', placeholder="Desired Username", css_class=""), - Field('first_name', placeholder="Your first name", css_class=""), - Field('last_name', placeholder="Your last name", css_class=""), - Field('email', placeholder="Your Email Address", css_class=""), - Field('district', css_class=""), - Field('phone_number', placeholder="Your 10 Digit Mobile Number", css_class="'"), - Field('gender', css_class=""), - Field('age', placeholder="Your age in numbers", css_class=""), - Field('skill', css_class=""), - Field('password1', placeholder="Password Confirmation", css_class=""), - Field('password2', placeholder="Password", css_class=""), + Field("username", placeholder="Desired Username", css_class=""), + Field("first_name", placeholder="Your first name", css_class=""), + Field("last_name", placeholder="Your last name", css_class=""), + Field("email", placeholder="Your Email Address", css_class=""), + Field("district", css_class=""), + Field("phone_number", placeholder="Your 10 Digit Mobile Number", css_class="'"), + Field("gender", css_class=""), + Field("age", placeholder="Your age in numbers", css_class=""), + Field("skill", css_class=""), + Field("password1", placeholder="Password Confirmation", css_class=""), + Field("password2", placeholder="Password", css_class=""), ) @@ -82,6 +82,6 @@ def __init__(self, *args, **kwargs): super(AuthenticationForm, self).__init__(*args, **kwargs) self.helper = FormHelper() self.helper.layout = Layout( - Field('username', placeholder=" Username", css_class=""), - Field('password', placeholder="Password", css_class=""), + Field("username", placeholder=" Username", css_class=""), + Field("password", placeholder="Password", css_class=""), ) diff --git a/care/users/models.py b/care/users/models.py index 0ec90fc5bc..e1a48ea30c 100644 --- a/care/users/models.py +++ b/care/users/models.py @@ -1,8 +1,7 @@ from django.contrib.auth.models import AbstractUser, UserManager +from django.core.validators import MaxValueValidator, MinValueValidator, RegexValidator from django.db import models from django.urls import reverse -from django.core.validators import RegexValidator -from django.core.validators import MaxValueValidator, MinValueValidator class CustomUserManager(UserManager): @@ -50,7 +49,7 @@ class User(AbstractUser): user_type = models.IntegerField(choices=TYPE_CHOICES, blank=False) district = models.IntegerField(choices=DISTRICT_CHOICES, blank=False) phone_number_regex = RegexValidator( - regex="^((\+91|91|0)[\- ]{0,1})?[456789]\d{9}$", + regex=r"^((\+91|91|0)[\- ]{0,1})?[456789]\d{9}$", message="Please Enter 10/11 digit mobile number or landline as 0", code="invalid_mobile", ) diff --git a/care/users/urls.py b/care/users/urls.py index 903cf5a57e..40bfbd0f35 100644 --- a/care/users/urls.py +++ b/care/users/urls.py @@ -1,37 +1,23 @@ +from django.contrib.auth.views import LogoutView from django.urls import path +from .views import SignupView, SinginView + # from care.users.views import ( # user_detail_view, # user_redirect_view, # user_update_view, # ) -from django.contrib.auth.views import LogoutView -from .views import SignupView, SinginView app_name = "users" urlpatterns = [ # path("~redirect/", view=user_redirect_view, name="redirect"), # path("~update/", view=user_update_view, name="update"), # path("/", view=user_detail_view, name="detail"), - path( - "signup/volunteer/", - SignupView.as_view(), - {"type": 20, "name": "Volunteer"}, - name="signup-volunteer", - ), - path( - "signup/doctor/", - SignupView.as_view(), - {"type": 5, "name": "Doctor"}, - name="signup-doctor", - ), - path( - "signup/staff/", - SignupView.as_view(), - {"type": 10, "name": "Hospital Administrator"}, - name="signup-staff", - ), + path("signup/volunteer/", SignupView.as_view(), {"type": 20, "name": "Volunteer"}, name="signup-volunteer",), + path("signup/doctor/", SignupView.as_view(), {"type": 5, "name": "Doctor"}, name="signup-doctor",), + path("signup/staff/", SignupView.as_view(), {"type": 10, "name": "Hospital Administrator"}, name="signup-staff",), path("signin/", SinginView.as_view(), name="signin"), path("logout/", LogoutView.as_view(), name="logout"), ] diff --git a/care/users/views.py b/care/users/views.py index ff831ce201..0ab529aac6 100644 --- a/care/users/views.py +++ b/care/users/views.py @@ -1,10 +1,10 @@ import logging -from django.shortcuts import render, redirect -from django.contrib.auth import login, authenticate +from django.contrib.auth import authenticate, login from django.contrib.auth.forms import AuthenticationForm -from django.views import View from django.http import HttpResponseRedirect +from django.shortcuts import redirect, render +from django.views import View from care.users.forms import CustomSignupForm, User @@ -20,11 +20,9 @@ class SignupView(View): def get(self, request, **kwargs): try: form = self.form_class() - if kwargs["type"] != User.TYPE_VALUE_MAP['Volunteer']: - form.fields.pop('skill') - return render( - request, self.template, {"form": form, "type": kwargs["name"]} - ) + if kwargs["type"] != User.TYPE_VALUE_MAP["Volunteer"]: + form.fields.pop("skill") + return render(request, self.template, {"form": form, "type": kwargs["name"]}) except Exception as e: logging.error(e) return HttpResponseRedirect("/500") diff --git a/config/api_router.py b/config/api_router.py index 40b258947e..e1aae19832 100644 --- a/config/api_router.py +++ b/config/api_router.py @@ -1,7 +1,7 @@ from django.conf import settings from rest_framework.routers import DefaultRouter, SimpleRouter -from care.facility.api.views import FacilityViewSet, AmbulanceViewSet +from care.facility.api.views import AmbulanceViewSet, FacilityViewSet from care.users.api.views import UserViewSet if settings.DEBUG: diff --git a/config/authentication.py b/config/authentication.py index 23e1178a1e..b07c369122 100644 --- a/config/authentication.py +++ b/config/authentication.py @@ -1,6 +1,5 @@ -from rest_framework_simplejwt.authentication import JWTAuthentication - from rest_framework.authentication import BasicAuthentication +from rest_framework_simplejwt.authentication import JWTAuthentication class CustomJWTAuthentication(JWTAuthentication): diff --git a/config/settings/base.py b/config/settings/base.py index 47a7aba3f5..ce8212acdc 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -2,9 +2,10 @@ Base settings to build other settings files upon. """ -import environ from datetime import timedelta +import environ + ROOT_DIR = environ.Path(__file__) - 3 # (care/config/settings/base.py - 3 = care/) APPS_DIR = ROOT_DIR.path("care") @@ -45,7 +46,6 @@ DATABASES["default"]["ATOMIC_REQUESTS"] = True DATABASES["default"]["ENGINE"] = "django.contrib.gis.db.backends.postgis" - # URLS # ------------------------------------------------------------------------------ # https://docs.djangoproject.com/en/dev/ref/settings/#root-urlconf @@ -56,7 +56,6 @@ # CollectFast COLLECTFAST_STRATEGY = "collectfast.strategies.boto3.Boto3Strategy" - # APPS # ------------------------------------------------------------------------------ DJANGO_APPS = [ @@ -103,7 +102,6 @@ ACCOUNT_FORMS = {"signup": "users.forms.CustomSignupForm"} - # https://docs.djangoproject.com/en/dev/ref/settings/#auth-user-model AUTH_USER_MODEL = "users.User" # https://docs.djangoproject.com/en/dev/ref/settings/#login-redirect-url @@ -123,9 +121,7 @@ ] # https://docs.djangoproject.com/en/dev/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ - { - "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator" - }, + {"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator"}, {"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator"}, {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"}, {"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"}, @@ -185,10 +181,7 @@ "OPTIONS": { # https://docs.djangoproject.com/en/dev/ref/settings/#template-loaders # https://docs.djangoproject.com/en/dev/ref/templates/api/#loader-types - "loaders": [ - "django.template.loaders.filesystem.Loader", - "django.template.loaders.app_directories.Loader", - ], + "loaders": ["django.template.loaders.filesystem.Loader", "django.template.loaders.app_directories.Loader",], # https://docs.djangoproject.com/en/dev/ref/settings/#template-context-processors "context_processors": [ "django.template.context_processors.debug", @@ -230,9 +223,7 @@ # EMAIL # ------------------------------------------------------------------------------ # https://docs.djangoproject.com/en/dev/ref/settings/#email-backend -EMAIL_BACKEND = env( - "DJANGO_EMAIL_BACKEND", default="django.core.mail.backends.smtp.EmailBackend" -) +EMAIL_BACKEND = env("DJANGO_EMAIL_BACKEND", default="django.core.mail.backends.smtp.EmailBackend") # https://docs.djangoproject.com/en/2.2/ref/settings/#email-timeout EMAIL_TIMEOUT = 5 @@ -253,23 +244,11 @@ LOGGING = { "version": 1, "disable_existing_loggers": False, - "formatters": { - "verbose": { - "format": "%(levelname)s %(asctime)s %(module)s " - "%(process)d %(thread)d %(message)s" - } - }, - "handlers": { - "console": { - "level": "DEBUG", - "class": "logging.StreamHandler", - "formatter": "verbose", - } - }, + "formatters": {"verbose": {"format": "%(levelname)s %(asctime)s %(module)s " "%(process)d %(thread)d %(message)s"}}, + "handlers": {"console": {"level": "DEBUG", "class": "logging.StreamHandler", "formatter": "verbose",}}, "root": {"level": "INFO", "handlers": ["console"]}, } - # django-allauth # ------------------------------------------------------------------------------ ACCOUNT_ALLOW_REGISTRATION = env.bool("DJANGO_ACCOUNT_ALLOW_REGISTRATION", True) @@ -284,7 +263,6 @@ # https://django-allauth.readthedocs.io/en/latest/configuration.html SOCIALACCOUNT_ADAPTER = "care.users.adapters.SocialAccountAdapter" - # Django Rest Framework # ------------------------------------------------------------------------------ @@ -310,18 +288,12 @@ LOGOUT_REDIRECT_URL = "/" STAFF_ACCOUNT_TYPE = 10 - # Simple JWT SIMPLE_JWT = { - "ACCESS_TOKEN_LIFETIME": timedelta( - minutes=env("JWT_ACCESS_TOKEN_LIFETIME", default=120) - ), - "REFRESH_TOKEN_LIFETIME": timedelta( - days=env("JWT_REFRESH_TOKEN_LIFETIME", default=7) - ), + "ACCESS_TOKEN_LIFETIME": timedelta(minutes=env("JWT_ACCESS_TOKEN_LIFETIME", default=120)), + "REFRESH_TOKEN_LIFETIME": timedelta(days=env("JWT_REFRESH_TOKEN_LIFETIME", default=7)), } - LOCATION_FIELD = { "search.provider": "google", "map.provider": "openstreetmap", diff --git a/config/settings/local.py b/config/settings/local.py index 4a9fd27815..efb5242f24 100644 --- a/config/settings/local.py +++ b/config/settings/local.py @@ -6,22 +6,14 @@ # https://docs.djangoproject.com/en/dev/ref/settings/#debug DEBUG = True # https://docs.djangoproject.com/en/dev/ref/settings/#secret-key -SECRET_KEY = env( - "DJANGO_SECRET_KEY", - default="eXZQzOzx8gV38rDG0Z0fFZWweUGl3LwMZ9aTKqJiXQTI0nKMh0Z7sbHfqT8KFEnd", -) +SECRET_KEY = env("DJANGO_SECRET_KEY", default="eXZQzOzx8gV38rDG0Z0fFZWweUGl3LwMZ9aTKqJiXQTI0nKMh0Z7sbHfqT8KFEnd",) # https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts ALLOWED_HOSTS = ["localhost", "0.0.0.0", "127.0.0.1", "*"] # CACHES # ------------------------------------------------------------------------------ # https://docs.djangoproject.com/en/dev/ref/settings/#caches -CACHES = { - "default": { - "BACKEND": "django.core.cache.backends.locmem.LocMemCache", - "LOCATION": "", - } -} +CACHES = {"default": {"BACKEND": "django.core.cache.backends.locmem.LocMemCache", "LOCATION": "",}} # EMAIL # ------------------------------------------------------------------------------ @@ -35,7 +27,6 @@ # http://whitenoise.evans.io/en/latest/django.html#using-whitenoise-in-development INSTALLED_APPS = ["whitenoise.runserver_nostatic"] + INSTALLED_APPS # noqa F405 - # django-debug-toolbar # ------------------------------------------------------------------------------ # https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#prerequisites @@ -50,7 +41,6 @@ # https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#internal-ips INTERNAL_IPS = ["127.0.0.1", "10.0.2.2"] - # django-extensions # ------------------------------------------------------------------------------ # https://django-extensions.readthedocs.io/en/latest/installation_instructions.html#configuration diff --git a/config/settings/production.py b/config/settings/production.py index 9454438667..6a87f2636f 100644 --- a/config/settings/production.py +++ b/config/settings/production.py @@ -2,7 +2,6 @@ import logging import sentry_sdk - from sentry_sdk.integrations.django import DjangoIntegration from sentry_sdk.integrations.logging import LoggingIntegration @@ -52,15 +51,11 @@ # TODO: set this to 60 seconds first and then to 518400 once you prove the former works SECURE_HSTS_SECONDS = 60 # https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-include-subdomains -SECURE_HSTS_INCLUDE_SUBDOMAINS = env.bool( - "DJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS", default=True -) +SECURE_HSTS_INCLUDE_SUBDOMAINS = env.bool("DJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS", default=True) # https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-preload SECURE_HSTS_PRELOAD = env.bool("DJANGO_SECURE_HSTS_PRELOAD", default=True) # https://docs.djangoproject.com/en/dev/ref/middleware/#x-content-type-options-nosniff -SECURE_CONTENT_TYPE_NOSNIFF = env.bool( - "DJANGO_SECURE_CONTENT_TYPE_NOSNIFF", default=True -) +SECURE_CONTENT_TYPE_NOSNIFF = env.bool("DJANGO_SECURE_CONTENT_TYPE_NOSNIFF", default=True) # STATIC # ------------------------ @@ -74,19 +69,14 @@ TEMPLATES[-1]["OPTIONS"]["loaders"] = [ # type: ignore[index] # noqa F405 ( "django.template.loaders.cached.Loader", - [ - "django.template.loaders.filesystem.Loader", - "django.template.loaders.app_directories.Loader", - ], + ["django.template.loaders.filesystem.Loader", "django.template.loaders.app_directories.Loader",], ) ] # EMAIL # ------------------------------------------------------------------------------ # https://docs.djangoproject.com/en/dev/ref/settings/#default-from-email -DEFAULT_FROM_EMAIL = env( - "DJANGO_DEFAULT_FROM_EMAIL", default="Care " -) +DEFAULT_FROM_EMAIL = env("DJANGO_DEFAULT_FROM_EMAIL", default="Care ") # https://docs.djangoproject.com/en/dev/ref/settings/#server-email SERVER_EMAIL = env("DJANGO_SERVER_EMAIL", default=DEFAULT_FROM_EMAIL) # https://docs.djangoproject.com/en/dev/ref/settings/#email-subject-prefix @@ -121,33 +111,14 @@ LOGGING = { "version": 1, "disable_existing_loggers": True, - "formatters": { - "verbose": { - "format": "%(levelname)s %(asctime)s %(module)s " - "%(process)d %(thread)d %(message)s" - } - }, - "handlers": { - "console": { - "level": "DEBUG", - "class": "logging.StreamHandler", - "formatter": "verbose", - } - }, + "formatters": {"verbose": {"format": "%(levelname)s %(asctime)s %(module)s " "%(process)d %(thread)d %(message)s"}}, + "handlers": {"console": {"level": "DEBUG", "class": "logging.StreamHandler", "formatter": "verbose",}}, "root": {"level": "INFO", "handlers": ["console"]}, "loggers": { - "django.db.backends": { - "level": "ERROR", - "handlers": ["console"], - "propagate": False, - }, + "django.db.backends": {"level": "ERROR", "handlers": ["console"], "propagate": False,}, # Errors logged by the SDK itself "sentry_sdk": {"level": "ERROR", "handlers": ["console"], "propagate": False}, - "django.security.DisallowedHost": { - "level": "ERROR", - "handlers": ["console"], - "propagate": False, - }, + "django.security.DisallowedHost": {"level": "ERROR", "handlers": ["console"], "propagate": False,}, }, } @@ -157,8 +128,7 @@ SENTRY_LOG_LEVEL = env.int("DJANGO_SENTRY_LOG_LEVEL", logging.INFO) sentry_logging = LoggingIntegration( - level=SENTRY_LOG_LEVEL, # Capture info and above as breadcrumbs - event_level=logging.ERROR, # Send errors as events + level=SENTRY_LOG_LEVEL, event_level=logging.ERROR, # Capture info and above as breadcrumbs # Send errors as events ) sentry_sdk.init(dsn=SENTRY_DSN, integrations=[sentry_logging, DjangoIntegration()]) diff --git a/config/settings/test.py b/config/settings/test.py index 48c5c874cf..272d1959c2 100644 --- a/config/settings/test.py +++ b/config/settings/test.py @@ -8,22 +8,14 @@ # GENERAL # ------------------------------------------------------------------------------ # https://docs.djangoproject.com/en/dev/ref/settings/#secret-key -SECRET_KEY = env( - "DJANGO_SECRET_KEY", - default="GlSRVXhTNJXx3Fnu5HUYlgeoMIXy3rl76CIhfOAEHtXE4jrGAEDbAWyzIpW7SVQn", -) +SECRET_KEY = env("DJANGO_SECRET_KEY", default="GlSRVXhTNJXx3Fnu5HUYlgeoMIXy3rl76CIhfOAEHtXE4jrGAEDbAWyzIpW7SVQn",) # https://docs.djangoproject.com/en/dev/ref/settings/#test-runner TEST_RUNNER = "django.test.runner.DiscoverRunner" # CACHES # ------------------------------------------------------------------------------ # https://docs.djangoproject.com/en/dev/ref/settings/#caches -CACHES = { - "default": { - "BACKEND": "django.core.cache.backends.locmem.LocMemCache", - "LOCATION": "", - } -} +CACHES = {"default": {"BACKEND": "django.core.cache.backends.locmem.LocMemCache", "LOCATION": "",}} # PASSWORDS # ------------------------------------------------------------------------------ @@ -35,10 +27,7 @@ TEMPLATES[-1]["OPTIONS"]["loaders"] = [ # type: ignore[index] # noqa F405 ( "django.template.loaders.cached.Loader", - [ - "django.template.loaders.filesystem.Loader", - "django.template.loaders.app_directories.Loader", - ], + ["django.template.loaders.filesystem.Loader", "django.template.loaders.app_directories.Loader",], ) ] diff --git a/config/urls.py b/config/urls.py index 797cfc54ac..50e8134092 100644 --- a/config/urls.py +++ b/config/urls.py @@ -1,18 +1,18 @@ from django.conf import settings +from django.conf.urls import url from django.conf.urls.static import static from django.contrib import admin from django.urls import include, path -from django.conf.urls import url from django.views import defaults as default_views from django.views.generic import TemplateView +from drf_yasg import openapi +from drf_yasg.views import get_schema_view +from rest_framework import permissions from rest_framework_simplejwt.views import ( TokenObtainPairView, TokenRefreshView, TokenVerifyView, ) -from rest_framework import permissions -from drf_yasg.views import get_schema_view -from drf_yasg import openapi from config import api_router @@ -32,28 +32,14 @@ urlpatterns = [ path("", TemplateView.as_view(template_name="pages/home.html"), name="home"), - path( - "ksdma/", TemplateView.as_view(template_name="pages/ksdma.html"), name="ksdma" - ), + path("ksdma/", TemplateView.as_view(template_name="pages/ksdma.html"), name="ksdma"), # API Docs - url( - r"^swagger(?P\.json|\.yaml)$", - schema_view.without_ui(cache_timeout=0), - name="schema-json", - ), - url( - r"^swagger/$", - schema_view.with_ui("swagger", cache_timeout=0), - name="schema-swagger-ui", - ), - url( - r"^redoc/$", schema_view.with_ui("redoc", cache_timeout=0), name="schema-redoc" - ), + url(r"^swagger(?P\.json|\.yaml)$", schema_view.without_ui(cache_timeout=0), name="schema-json",), + url(r"^swagger/$", schema_view.with_ui("swagger", cache_timeout=0), name="schema-swagger-ui",), + url(r"^redoc/$", schema_view.with_ui("redoc", cache_timeout=0), name="schema-redoc"), # Rest API path("api/v1/auth/login/", TokenObtainPairView.as_view(), name="token_obtain_pair"), - path( - "api/v1/auth/token/refresh/", TokenRefreshView.as_view(), name="token_refresh" - ), + path("api/v1/auth/token/refresh/", TokenRefreshView.as_view(), name="token_refresh"), path("api/v1/auth/token/verify/", TokenVerifyView.as_view(), name="token_verify"), # Django Admin, use {% url 'admin:index' %} path(settings.ADMIN_URL, admin.site.urls), @@ -70,21 +56,9 @@ # This allows the error pages to be debugged during development, just visit # these url in browser to see how these error pages look like. urlpatterns += [ - path( - "400/", - default_views.bad_request, - kwargs={"exception": Exception("Bad Request!")}, - ), - path( - "403/", - default_views.permission_denied, - kwargs={"exception": Exception("Permission Denied")}, - ), - path( - "404/", - default_views.page_not_found, - kwargs={"exception": Exception("Page not Found")}, - ), + path("400/", default_views.bad_request, kwargs={"exception": Exception("Bad Request!")},), + path("403/", default_views.permission_denied, kwargs={"exception": Exception("Permission Denied")},), + path("404/", default_views.page_not_found, kwargs={"exception": Exception("Page not Found")},), path("500/", default_views.server_error), ] if "debug_toolbar" in settings.INSTALLED_APPS: diff --git a/config/wsgi.py b/config/wsgi.py index f92a3754ff..3f8ce6fce1 100644 --- a/config/wsgi.py +++ b/config/wsgi.py @@ -20,9 +20,7 @@ # This allows easy placement of apps within the interior # care directory. -app_path = os.path.abspath( - os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir) -) +app_path = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir)) sys.path.append(os.path.join(app_path, "care")) # We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks # if running multiple sites in the same mod_wsgi process. To fix this, use diff --git a/merge_production_dotenvs_in_dotenv.py b/merge_production_dotenvs_in_dotenv.py index 4e70e2adbd..0668c6e5ef 100644 --- a/merge_production_dotenvs_in_dotenv.py +++ b/merge_production_dotenvs_in_dotenv.py @@ -12,9 +12,7 @@ DOTENV_FILE_PATH = os.path.join(ROOT_DIR_PATH, ".env") -def merge( - output_file_path: str, merged_file_paths: Sequence[str], append_linesep: bool = True -) -> None: +def merge(output_file_path: str, merged_file_paths: Sequence[str], append_linesep: bool = True) -> None: with open(output_file_path, "w") as output_file: for merged_file_path in merged_file_paths: with open(merged_file_path, "r") as merged_file: diff --git a/setup.cfg b/setup.cfg index 5f7d9b655e..df68f3f658 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,9 @@ [flake8] max-line-length = 120 exclude = .tox,.git,*/migrations/*,*/static/CACHE/*,docs,node_modules +extend-ignore = + # See https://github.com/PyCQA/pycodestyle/issues/373 + E203, E231, [pycodestyle] max-line-length = 120 @@ -21,3 +24,6 @@ django_settings_module = config.settings.test [mypy-*.migrations.*] # Django migrations should not produce any errors: ignore_errors = True + +[isort] +known_third_party = allauth,crispy_forms,django,django_filters,drf_extra_fields,drf_yasg,environ,location_field,pytest,rest_framework,rest_framework_simplejwt,sentry_sdk