Skip to content

Commit

Permalink
Merge pull request #197 from City-of-Helsinki/develop
Browse files Browse the repository at this point in the history
Release 20210108
  • Loading branch information
Tomi Järvi authored Jan 8, 2021
2 parents 40aaa6c + ca29159 commit c39dbc6
Show file tree
Hide file tree
Showing 19 changed files with 163 additions and 43 deletions.
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ python:
- "3.7"

addons:
postgresql: '9.5'
postgresql: '10'
apt:
packages:
- postgresql-9.5-postgis-2.4
- postgresql-10-postgis-2.4

install:
- pip install -U pip
Expand All @@ -33,7 +33,7 @@ script:
- python manage.py makemigrations --dry-run --check
- black --check .
- flake8
- isort --check-only --diff
- isort . --check-only --diff
- pytest -ra -vvv --doctest-modules --cov=.
- ./run-type-checks

Expand Down
5 changes: 0 additions & 5 deletions batchrun/.isort.cfg

This file was deleted.

10 changes: 9 additions & 1 deletion batchrun/admin.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from django.contrib import admin
from rangefilter.filter import DateRangeFilter # type: ignore

from .admin_utils import PreciseTimeFormatter, ReadOnlyAdmin
from .models import (
Expand All @@ -23,14 +24,21 @@ class JobAdmin(admin.ModelAdmin):
list_display = ["name", "comment", "command"]


class JobRunLogEntryInline(admin.TabularInline):
model = JobRunLogEntry
show_change_link = True


@admin.register(JobRun)
class JobRunAdmin(ReadOnlyAdmin):
date_hierarchy = "started_at"
inlines = [JobRunLogEntryInline]
list_display = ["started_at_p", "stopped_at_p", "job", "exit_code"]
list_filter = ["exit_code"]
list_filter = ("started_at", ("started_at", DateRangeFilter), "job", "exit_code")
# auto_now_add_fields don't show even in readonlyadmin.
# Therefore we'll add all the fields by hand in a suitable order
readonly_fields = ("job", "pid", "started_at_p", "stopped_at_p", "exit_code")
search_fields = ["log_entries__text"]
exclude = ["stopped_at"]

started_at_p = PreciseTimeFormatter(JobRun, "started_at")
Expand Down
4 changes: 2 additions & 2 deletions batchrun/api/viewsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class Meta:


class JobRunViewSet(viewsets.ReadOnlyModelViewSet): # type: ignore
queryset = models.JobRun.objects.all()
queryset = models.JobRun.objects.all_with_deleted() # type: ignore
serializer_class = JobRunSerializer
filterset_fields = ["exit_code"]

Expand All @@ -40,6 +40,6 @@ class Meta:


class JobRunLogEntryViewSet(viewsets.ReadOnlyModelViewSet): # type: ignore
queryset = models.JobRunLogEntry.objects.all()
queryset = models.JobRunLogEntry.objects.all_with_deleted() # type: ignore
serializer_class = JobRunLogEntrySerializer
filterset_fields = ["run", "kind"]
2 changes: 1 addition & 1 deletion batchrun/job_launching.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def run_job(job: Job) -> JobRun:
launcher = JobRunLauncher(job_run)
launcher.start()
launcher.join()
return job_run
return job_run # type: ignore


class JobRunLauncher(multiprocessing.Process):
Expand Down
2 changes: 1 addition & 1 deletion batchrun/management/commands/batchrun_execute_job_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ def add_arguments(cls, parser: argparse.ArgumentParser) -> None:

def handle(self, *args: Any, **options: Any) -> None:
job_run_id = options.get("job_run_id")
job_run = JobRun.objects.get(pk=job_run_id) # type: ignore
job_run = JobRun.objects.get(pk=job_run_id)
execute_job_run(job_run)
13 changes: 3 additions & 10 deletions batchrun/management/commands/drop_old_log_entries.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from dateutil.relativedelta import relativedelta
from django.core.management.base import BaseCommand

from ...models import JobRun, JobRunLogEntry
from ...models import JobRun


class Command(BaseCommand):
Expand Down Expand Up @@ -33,13 +33,6 @@ def handle(self, *args: Any, **options: Any) -> None:
JobRun.objects.count(),
)
)
log_entries_to_delete = JobRunLogEntry.objects.filter(
run__in=runs_before_cutoff
)
self.stdout.write(
"Proceeding to delete {} / {} stored JobRunLogEntries".format(
log_entries_to_delete.count(), JobRunLogEntry.objects.count()
)
)
log_entries_to_delete.delete()
runs_before_cutoff.delete()

self.stdout.write("Done!")
34 changes: 34 additions & 0 deletions batchrun/migrations/0002_add_safedelete_to_logs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Generated by Django 2.2.13 on 2020-12-16 09:31

import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("batchrun", "0001_initial"),
]

operations = [
migrations.AddField(
model_name="jobrun",
name="deleted",
field=models.DateTimeField(editable=False, null=True),
),
migrations.AddField(
model_name="jobrunlogentry",
name="deleted",
field=models.DateTimeField(editable=False, null=True),
),
migrations.AlterField(
model_name="jobrunlogentry",
name="run",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="log_entries",
to="batchrun.JobRun",
verbose_name="run",
),
),
]
9 changes: 6 additions & 3 deletions batchrun/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from django.utils.translation import ugettext
from django.utils.translation import ugettext_lazy as _
from enumfields import EnumField
from safedelete import SOFT_DELETE_CASCADE # type: ignore
from safedelete.models import SafeDeleteModel

from ._times import utc_now
Expand Down Expand Up @@ -250,11 +251,13 @@ def update_run_queue(self, max_items_to_create: int = 10) -> None:
items.exclude(pk__in=fresh_ids).delete()


class JobRun(models.Model):
class JobRun(SafeDeleteModel):
"""
Instance of a job currently running or ran in the past.
"""

_safedelete_policy = SOFT_DELETE_CASCADE

job = models.ForeignKey(Job, on_delete=models.PROTECT, verbose_name=_("job"))
pid = models.IntegerField(
null=True,
Expand All @@ -280,7 +283,7 @@ def __str__(self) -> str:
return f"{self.job} [{self.pid}] ({self.started_at:%Y-%m-%dT%H:%M})"


class JobRunLogEntry(models.Model):
class JobRunLogEntry(SafeDeleteModel):
"""
Entry in a log for a run of a job.
Expand All @@ -293,7 +296,7 @@ class JobRunLogEntry(models.Model):

run = models.ForeignKey(
JobRun,
on_delete=models.PROTECT,
on_delete=models.CASCADE,
related_name="log_entries",
verbose_name=_("run"),
)
Expand Down
4 changes: 2 additions & 2 deletions docker/postgres/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
FROM postgres:9.5
FROM postgres:10.15

RUN apt-get update \
&& apt-get install --no-install-recommends -y \
postgis postgresql-9.5-postgis-2.4 postgresql-9.5-postgis-2.4-scripts
postgis postgresql-10-postgis-2.4 postgresql-10-postgis-2.4-scripts

RUN localedef -i fi_FI -c -f UTF-8 -A /usr/share/locale/locale.alias fi_FI.UTF-8

Expand Down
19 changes: 19 additions & 0 deletions leasing/models/land_area.py
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,25 @@ def save(self, *args, **kwargs):
if self.id and not self.tracker.changed():
return

# There can be only one master plan unit per lease area and identifier
if self.is_master:
master_plan_unit_count = (
PlanUnit.objects.filter(
lease_area=self.lease_area,
identifier=self.identifier,
is_master=True,
)
.exclude(id=self.id)
.count()
)
if master_plan_unit_count:
raise Exception(
_(
"The master plan unit has already created. "
"There can be only one master plan unit per lease area and identifier."
)
)

skip_modified_update = kwargs.pop("skip_modified_update", False)
if skip_modified_update:
modified_at_field = self._meta.get_field("modified_at")
Expand Down
4 changes: 2 additions & 2 deletions leasing/serializers/invoice.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ def __init__(self, instance=None, data=empty, **kwargs):
super().__init__(instance=instance, data=data, **kwargs)

# Lease field must be added dynamically to prevent circular imports
from leasing.serializers.lease import LeaseSuccinctSerializer
from leasing.models.lease import Lease
from leasing.serializers.lease import LeaseSuccinctSerializer

self.fields["lease"] = InstanceDictPrimaryKeyRelatedField(
instance_class=Lease,
Expand Down Expand Up @@ -507,8 +507,8 @@ def __init__(self, instance=None, data=empty, **kwargs):
super().__init__(instance=instance, data=data, **kwargs)

# Lease field must be added dynamically to prevent circular imports
from leasing.serializers.lease import LeaseSuccinctSerializer
from leasing.models.lease import Lease
from leasing.serializers.lease import LeaseSuccinctSerializer

self.fields["lease"] = InstanceDictPrimaryKeyRelatedField(
instance_class=Lease,
Expand Down
19 changes: 19 additions & 0 deletions leasing/tests/models/test_land_area.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import pytest


@pytest.mark.django_db
def test_plan_unit_cannot_create_another_master_plan_unit(
lease_test_data, plan_unit_factory
):
master_plan_unit = plan_unit_factory(
area=100,
lease_area=lease_test_data["lease_area"],
identifier="1234",
is_master=True,
)

another_master_plan_unit = master_plan_unit
another_master_plan_unit.pk = None

with pytest.raises(Exception):
another_master_plan_unit.save()
Loading

0 comments on commit c39dbc6

Please sign in to comment.