Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ jobs:
- name: Setup uv python environment
run: uv venv

- name: Install system deps for pycairo
run: |
sudo apt-get update
sudo apt-get install -y libcairo2-dev pkg-config

- name: uv lock check
run: uv lock --locked --offline

Expand Down
2 changes: 1 addition & 1 deletion .python-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.11
~=3.11.13
6 changes: 4 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
FROM python:3.11-bullseye
COPY --from=ghcr.io/astral-sh/uv:0.6.2 /uv /uvx /bin/
COPY --from=ghcr.io/astral-sh/uv:0.11.3 /uv /uvx /bin/

LABEL maintainer="GO Dev <go-dev@ifrc.org>"
LABEL org.opencontainers.image.source="https://github.com/IFRCGo/go-api"

ENV PYTHONUNBUFFERED=1

ENV UV_SYSTEM_PYTHON=1
ENV UV_COMPILE_BYTECODE=1
ENV UV_LINK_MODE=copy
ENV UV_PROJECT_ENVIRONMENT="/usr/local/"
Expand All @@ -31,7 +32,8 @@ WORKDIR $HOME
RUN --mount=type=cache,target=$UV_CACHE_DIR \
--mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
uv sync --frozen --no-install-project --all-groups
uv lock --locked --offline \
&& uv sync --frozen --no-install-project --all-groups

# To avoid some SyntaxWarnings ("is" with a literal), still needed on 20241024:
ENV AZUREROOT=/usr/local/lib/python3.11/site-packages/azure/storage/
Expand Down
8 changes: 4 additions & 4 deletions api/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -952,7 +952,7 @@ def queryset(self, request, queryset):
return queryset


class DistrictAdmin(geoadmin.OSMGeoAdmin, CompareVersionAdmin, RegionRestrictedAdmin):
class DistrictAdmin(geoadmin.GISModelAdmin, CompareVersionAdmin, RegionRestrictedAdmin):

country_in = "country__pk__in"
region_in = "country__region__in"
Expand Down Expand Up @@ -981,7 +981,7 @@ class CountrySupportingPartnerAdmin(admin.TabularInline):
model = models.CountrySupportingPartner


class CountryAdmin(geoadmin.OSMGeoAdmin, CompareVersionAdmin, RegionRestrictedAdmin, TranslationAdmin):
class CountryAdmin(geoadmin.GISModelAdmin, CompareVersionAdmin, RegionRestrictedAdmin, TranslationAdmin):
country_in = "pk__in"
list_filter = ("record_type", "in_search", "independent", "disputed")
list_display = ("__str__", "record_type", "iso3")
Expand All @@ -1005,7 +1005,7 @@ class CountryAdmin(geoadmin.OSMGeoAdmin, CompareVersionAdmin, RegionRestrictedAd
exclude = ("key_priorities",)


class RegionAdmin(geoadmin.OSMGeoAdmin, CompareVersionAdmin, RegionRestrictedAdmin, TranslationAdmin):
class RegionAdmin(geoadmin.GISModelAdmin, CompareVersionAdmin, RegionRestrictedAdmin, TranslationAdmin):
country_in = None
region_in = "pk__in"
inlines = [
Expand Down Expand Up @@ -1041,7 +1041,7 @@ def queryset(self, request, queryset):
return queryset


class Admin2Admin(geoadmin.OSMGeoAdmin, CompareVersionAdmin, RegionRestrictedAdmin):
class Admin2Admin(geoadmin.GISModelAdmin, CompareVersionAdmin, RegionRestrictedAdmin):
search_fields = ("name", "admin1__country__name")
list_filter = (IsDeprecatedFilter, Admin1IsDeprecatedFilter, CountryIsDeprecatedFilter2)
modifiable = True
Expand Down
15 changes: 8 additions & 7 deletions api/management/commands/index_and_notify.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import html
from datetime import datetime, timedelta, timezone
from datetime import timedelta

from django.conf import settings
from django.contrib.auth.models import User
from django.core.management.base import BaseCommand
from django.db.models import DurationField, ExpressionWrapper, F, Q, Sum
from django.db.models.query import QuerySet
from django.template.loader import render_to_string
from django.utils import timezone
from django.utils.html import strip_tags
from elasticsearch.helpers import bulk
from sentry_sdk.crons import monitor
Expand Down Expand Up @@ -80,23 +81,23 @@ class Command(BaseCommand):

# Digest mode duration is 5 minutes once a week
def is_digest_mode(self):
today = datetime.now(timezone.utc)
today = timezone.now()
weekdayhourmin = int(today.strftime("%w%H%M"))
return digest_time <= weekdayhourmin and weekdayhourmin < digest_time + 5

def is_daily_checkup_time(self):
today = datetime.now(timezone.utc)
today = timezone.now()
hourmin = int(today.strftime("%H%M"))
return daily_retro <= hourmin and hourmin < daily_retro + 5

def diff_9_minutes(self):
return datetime.now(timezone.utc) - time_9_minutes
return timezone.now() - time_9_minutes

def diff_1_day(self):
return datetime.now(timezone.utc) - time_1_day
return timezone.now() - time_1_day

def diff_1_week(self):
return datetime.now(timezone.utc) - time_1_week
return timezone.now() - time_1_week

def gather_country_and_region(self, records):
# Appeals only, since these have a single country/region
Expand Down Expand Up @@ -345,7 +346,7 @@ def get_record_display(self, rtype, count):
return display

def get_weekly_digest_data(self, field):
today = datetime.now(timezone.utc)
today = timezone.now()
if field == "dref":
return Appeal.objects.filter(end_date__gt=today, atype=0).count()
elif field == "ea":
Expand Down
8 changes: 5 additions & 3 deletions api/management/commands/ingest_appeal_docs.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
from collections import defaultdict
from datetime import datetime, timezone
from datetime import datetime
from datetime import timezone as datetime_timezone

from bs4 import BeautifulSoup
from dateutil.relativedelta import relativedelta
from django.core.exceptions import ObjectDoesNotExist
from django.core.management.base import BaseCommand
from django.utils import timezone
from urllib3 import PoolManager

from api.logger import logger
Expand Down Expand Up @@ -46,7 +48,7 @@ def makelist(self, table):
def parse_date(self, date_string):
# 21 Dec 2017
timeformat = "%d %b %Y"
return datetime.strptime(date_string.strip(), timeformat).replace(tzinfo=timezone.utc)
return datetime.strptime(date_string.strip(), timeformat).replace(tzinfo=datetime_timezone.utc)

def handle(self, *args, **options):
logger.info("Starting appeal document ingest")
Expand Down Expand Up @@ -80,7 +82,7 @@ def handle(self, *args, **options):
qset = Appeal.objects.all()
else:
# By default, only check appeals for the past 3 months where Appeal Documents is 0
now = datetime.now().replace(tzinfo=timezone.utc)
now = timezone.now()
six_months_ago = now - relativedelta(months=6)
# This was the original qset, but it wouldn't get newer docs for the same Appeals
# qset = Appeal.objects.filter(appealdocument__isnull=True).filter(end_date__gt=six_months_ago)
Expand Down
5 changes: 3 additions & 2 deletions api/management/commands/ingest_appealdocs.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from datetime import datetime, timezone
from datetime import datetime
from datetime import timezone as datetime_timezone

import requests
from django.conf import settings
Expand All @@ -21,7 +22,7 @@ class Command(BaseCommand):
@staticmethod
def parse_date(date_string):
timeformat = "%Y-%m-%dT%H:%M:%S"
return datetime.strptime(date_string[:18], timeformat).replace(tzinfo=timezone.utc)
return datetime.strptime(date_string[:18], timeformat).replace(tzinfo=datetime_timezone.utc)

def load(self, url: str, is_fednet):
codes = Appeal.objects.values_list("code", flat=True)
Expand Down
5 changes: 3 additions & 2 deletions api/management/commands/ingest_appeals.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import json
import os
from datetime import datetime, timedelta, timezone
from datetime import datetime, timedelta
from datetime import timezone as datetime_timezone

from django.conf import settings
from django.core.management.base import BaseCommand
Expand Down Expand Up @@ -38,7 +39,7 @@ class Command(BaseCommand):

def parse_date(self, date_string):
timeformat = "%Y-%m-%dT%H:%M:%S"
return datetime.strptime(date_string[:18], timeformat).replace(tzinfo=timezone.utc)
return datetime.strptime(date_string[:18], timeformat).replace(tzinfo=datetime_timezone.utc)

def create_bilaterals_dict(self, records):
"""Aggregate amounts (rec['AmountCHF']) of Bilateral records"""
Expand Down
5 changes: 3 additions & 2 deletions api/management/commands/ingest_deployments.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from datetime import datetime, timezone
from datetime import datetime
from datetime import timezone as datetime_timezone

import requests

Expand All @@ -16,7 +17,7 @@ class Command(BaseCommand):
def parse_date(self, date_string):
# 21Dec2017
timeformat = "%d%b%Y"
return datetime.strptime(date_string.strip(), timeformat).replace(tzinfo=timezone.utc)
return datetime.strptime(date_string.strip(), timeformat).replace(tzinfo=datetime_timezone.utc)

def handle(self, *args, **options):
logger.info("Starting Deployment ingest")
Expand Down
2 changes: 1 addition & 1 deletion api/management/commands/ingest_mdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ def handle(self, *args, **options):
"name": report_name if len(report_name) else report_dtype.name,
"summary": report_description,
"dtype": report_dtype,
"disaster_start_date": datetime.utcnow().replace(tzinfo=timezone.utc),
"disaster_start_date": timezone.now(),
"auto_generated": True,
"auto_generated_source": SOURCES["report_ingest"],
}
Expand Down
8 changes: 5 additions & 3 deletions api/management/commands/sync_appealdocs.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from datetime import datetime, timezone
from datetime import datetime
from datetime import timezone as datetime_timezone

import requests
from dateutil.relativedelta import relativedelta
from django.conf import settings
from django.core.management.base import BaseCommand
from django.utils import timezone
from sentry_sdk.crons import monitor

from api.logger import logger
Expand Down Expand Up @@ -36,7 +38,7 @@ def add_arguments(self, parser):

def parse_date(self, date_string):
timeformat = "%Y-%m-%dT%H:%M:%S"
return datetime.strptime(date_string[:18], timeformat).replace(tzinfo=timezone.utc)
return datetime.strptime(date_string[:18], timeformat).replace(tzinfo=datetime_timezone.utc)

@monitor(monitor_slug=SentryMonitor.SYNC_APPEALDOCS)
def handle(self, *args, **options):
Expand All @@ -49,7 +51,7 @@ def handle(self, *args, **options):
qset = Appeal.objects.all()
else:
# By default, only check appeals for the past 6 months where Appeal Documents is 0
now = datetime.now().replace(tzinfo=timezone.utc)
now = timezone.now()
six_months_ago = now - relativedelta(months=6)
# This was the original qset, but it wouldn't get newer docs for the same Appeals
# qset = Appeal.objects.filter(appealdocument__isnull=True).filter(end_date__gt=six_months_ago)
Expand Down
5 changes: 3 additions & 2 deletions api/management/commands/user_registration_reminder.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from datetime import datetime, timedelta, timezone
from datetime import timedelta

from django.core.management.base import BaseCommand
from django.template.loader import render_to_string
from django.utils import timezone
from sentry_sdk.crons import monitor

from api.models import Region, UserRegion
Expand All @@ -14,7 +15,7 @@ class Command(BaseCommand):
help = "Send reminder about the pending registrations"

def diff_3_day(self):
return datetime.utcnow().replace(tzinfo=timezone.utc) - timedelta(days=3)
return timezone.now() - timedelta(days=3)

@monitor(monitor_slug=SentryMonitor.USER_REGISTRATION_REMINDER)
def handle(self, *args, **options):
Expand Down
5 changes: 3 additions & 2 deletions api/receivers.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json
from datetime import datetime
from datetime import timezone as datetime_timezone

from django.db import transaction
from django.db.models import Q
Expand Down Expand Up @@ -224,7 +225,7 @@ def add_update_appeal_history(sender, instance, created, **kwargs):
amount_funded=instance.amount_funded,
valid_from=now,
# TODO: use coalesce to fill valid_to instead of defining here.
valid_to=datetime(2200, 1, 1, tzinfo=timezone.utc),
valid_to=datetime(2200, 1, 1, tzinfo=datetime_timezone.utc),
start_date=instance.start_date,
end_date=instance.end_date,
appeal=instance,
Expand Down Expand Up @@ -262,7 +263,7 @@ def add_update_appeal_history(sender, instance, created, **kwargs):
amount_funded=instance.amount_funded,
valid_from=now,
# TODO: use coalesce to fill valid_to instead of defining here.
valid_to=datetime(2200, 1, 1, tzinfo=timezone.utc),
valid_to=datetime(2200, 1, 1, tzinfo=datetime_timezone.utc),
start_date=instance.start_date,
end_date=instance.end_date,
appeal=instance,
Expand Down
8 changes: 4 additions & 4 deletions api/templates/admin/includes/fieldset.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
<div class="description">{{ fieldset.description|safe }}</div>
{% endif %}
{% for line in fieldset %}
<div class="form-row{% if line.fields|length_is:'1' and line.errors %} errors{% endif %}{% if not line.has_visible_field %} hidden{% endif %}{% for field in line %}{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% endfor %}">
{% if line.fields|length_is:'1' %}{{ line.errors }}{% endif %}
<div class="form-row{% if line.fields|length == 1 and line.errors %} errors{% endif %}{% if not line.has_visible_field %} hidden{% endif %}{% for field in line %}{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% endfor %}">
{% if line.fields|length == 1 %}{{ line.errors }}{% endif %}
{% for field in line %}
<div{% if not line.fields|length_is:'1' %} class="field-box{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% if not field.is_readonly and field.errors %} errors{% endif %}{% if field.field.is_hidden %} hidden{% endif %}"{% elif field.is_checkbox %} class="checkbox-row"{% endif %}>
{% if not line.fields|length_is:'1' and not field.is_readonly %}{{ field.errors }}{% endif %}
<div{% if not line.fields|length == 1 %} class="field-box{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% if not field.is_readonly and field.errors %} errors{% endif %}{% if field.field.is_hidden %} hidden{% endif %}"{% elif field.is_checkbox %} class="checkbox-row"{% endif %}>
{% if not line.fields|length == 1 and not field.is_readonly %}{{ field.errors }}{% endif %}
{% if field.is_checkbox %}
{{ field.field }}{{ field.label_tag }}
{% else %}
Expand Down
Loading
Loading