Format all python files using the formatter
Run `git ls-files '*.py' | xargs black`
Issue: HIC-161
Change-Id: I1619e6296bc4036504c5bb73128f769a1b7b688d
diff --git a/crashreports/admin.py b/crashreports/admin.py
index 7133070..97b32e0 100644
--- a/crashreports/admin.py
+++ b/crashreports/admin.py
@@ -8,15 +8,18 @@
@admin.register(Crashreport)
class CrashreportAdmin(admin.ModelAdmin):
pass
-
+
+
@admin.register(HeartBeat)
class CrashreportAdmin(admin.ModelAdmin):
pass
+
@admin.register(LogFile)
class CrashreportAdmin(admin.ModelAdmin):
pass
+
@admin.register(Device)
class CrashreportAdmin(admin.ModelAdmin):
pass
diff --git a/crashreports/apps.py b/crashreports/apps.py
index d651203..dacae51 100644
--- a/crashreports/apps.py
+++ b/crashreports/apps.py
@@ -4,4 +4,4 @@
class crashreportsConfig(AppConfig):
- name = 'crashreports'
+ name = "crashreports"
diff --git a/crashreports/migrations/0001_initial.py b/crashreports/migrations/0001_initial.py
index effb757..4542b4b 100644
--- a/crashreports/migrations/0001_initial.py
+++ b/crashreports/migrations/0001_initial.py
@@ -16,75 +16,179 @@
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
- ('taggit', '0002_auto_20150616_2121'),
+ ("taggit", "0002_auto_20150616_2121"),
]
operations = [
migrations.CreateModel(
- name='Crashreport',
+ name="Crashreport",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('is_fake_report', models.BooleanField(default=False)),
- ('app_version', models.IntegerField()),
- ('uptime', models.CharField(max_length=200)),
- ('build_fingerprint', models.CharField(max_length=200)),
- ('boot_reason', models.CharField(max_length=200)),
- ('power_on_reason', models.CharField(max_length=200)),
- ('power_off_reason', models.CharField(max_length=200)),
- ('date', models.DateTimeField()),
- ('device_local_id', models.PositiveIntegerField(blank=True)),
- ('next_logfile_key', models.PositiveIntegerField(default=1)),
- ('created_at', models.DateTimeField(auto_now_add=True)),
+ (
+ "id",
+ models.AutoField(
+ auto_created=True,
+ primary_key=True,
+ serialize=False,
+ verbose_name="ID",
+ ),
+ ),
+ ("is_fake_report", models.BooleanField(default=False)),
+ ("app_version", models.IntegerField()),
+ ("uptime", models.CharField(max_length=200)),
+ ("build_fingerprint", models.CharField(max_length=200)),
+ ("boot_reason", models.CharField(max_length=200)),
+ ("power_on_reason", models.CharField(max_length=200)),
+ ("power_off_reason", models.CharField(max_length=200)),
+ ("date", models.DateTimeField()),
+ ("device_local_id", models.PositiveIntegerField(blank=True)),
+ ("next_logfile_key", models.PositiveIntegerField(default=1)),
+ ("created_at", models.DateTimeField(auto_now_add=True)),
],
),
migrations.CreateModel(
- name='Device',
+ name="Device",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('uuid', models.CharField(default=uuid.uuid4, editable=False, max_length=64, unique=True)),
- ('imei', models.CharField(blank=True, max_length=32, null=True)),
- ('board_date', models.DateTimeField(blank=True, null=True)),
- ('chipset', models.CharField(blank=True, max_length=200, null=True)),
- ('last_heartbeat', models.DateTimeField(blank=True, null=True)),
- ('token', models.CharField(blank=True, max_length=200, null=True)),
- ('next_per_crashreport_key', models.PositiveIntegerField(default=1)),
- ('next_per_heartbeat_key', models.PositiveIntegerField(default=1)),
- ('tags', taggit.managers.TaggableManager(blank=True, help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags')),
- ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='Hiccup_Device', to=settings.AUTH_USER_MODEL)),
+ (
+ "id",
+ models.AutoField(
+ auto_created=True,
+ primary_key=True,
+ serialize=False,
+ verbose_name="ID",
+ ),
+ ),
+ (
+ "uuid",
+ models.CharField(
+ default=uuid.uuid4,
+ editable=False,
+ max_length=64,
+ unique=True,
+ ),
+ ),
+ (
+ "imei",
+ models.CharField(blank=True, max_length=32, null=True),
+ ),
+ ("board_date", models.DateTimeField(blank=True, null=True)),
+ (
+ "chipset",
+ models.CharField(blank=True, max_length=200, null=True),
+ ),
+ ("last_heartbeat", models.DateTimeField(blank=True, null=True)),
+ (
+ "token",
+ models.CharField(blank=True, max_length=200, null=True),
+ ),
+ (
+ "next_per_crashreport_key",
+ models.PositiveIntegerField(default=1),
+ ),
+ (
+ "next_per_heartbeat_key",
+ models.PositiveIntegerField(default=1),
+ ),
+ (
+ "tags",
+ taggit.managers.TaggableManager(
+ blank=True,
+ help_text="A comma-separated list of tags.",
+ through="taggit.TaggedItem",
+ to="taggit.Tag",
+ verbose_name="Tags",
+ ),
+ ),
+ (
+ "user",
+ models.OneToOneField(
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name="Hiccup_Device",
+ to=settings.AUTH_USER_MODEL,
+ ),
+ ),
],
),
migrations.CreateModel(
- name='HeartBeat',
+ name="HeartBeat",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('app_version', models.IntegerField()),
- ('uptime', models.CharField(max_length=200)),
- ('build_fingerprint', models.CharField(max_length=200)),
- ('date', models.DateTimeField()),
- ('device_local_id', models.PositiveIntegerField(blank=True)),
- ('created_at', models.DateTimeField(auto_now_add=True)),
- ('device', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='crashreports.Device')),
+ (
+ "id",
+ models.AutoField(
+ auto_created=True,
+ primary_key=True,
+ serialize=False,
+ verbose_name="ID",
+ ),
+ ),
+ ("app_version", models.IntegerField()),
+ ("uptime", models.CharField(max_length=200)),
+ ("build_fingerprint", models.CharField(max_length=200)),
+ ("date", models.DateTimeField()),
+ ("device_local_id", models.PositiveIntegerField(blank=True)),
+ ("created_at", models.DateTimeField(auto_now_add=True)),
+ (
+ "device",
+ models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ to="crashreports.Device",
+ ),
+ ),
],
),
migrations.CreateModel(
- name='LogFile',
+ name="LogFile",
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('logfile_type', models.TextField(default='last_kmsg', max_length=36)),
- ('logfile', models.FileField(max_length=500, upload_to=crashreports.models.crashreport_file_name)),
- ('crashreport_local_id', models.PositiveIntegerField(blank=True)),
- ('created_at', models.DateTimeField(auto_now_add=True)),
- ('crashreport', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='crashreports.Crashreport')),
+ (
+ "id",
+ models.AutoField(
+ auto_created=True,
+ primary_key=True,
+ serialize=False,
+ verbose_name="ID",
+ ),
+ ),
+ (
+ "logfile_type",
+ models.TextField(default="last_kmsg", max_length=36),
+ ),
+ (
+ "logfile",
+ models.FileField(
+ max_length=500,
+ upload_to=crashreports.models.crashreport_file_name,
+ ),
+ ),
+ (
+ "crashreport_local_id",
+ models.PositiveIntegerField(blank=True),
+ ),
+ ("created_at", models.DateTimeField(auto_now_add=True)),
+ (
+ "crashreport",
+ models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ to="crashreports.Crashreport",
+ ),
+ ),
],
),
migrations.AddField(
- model_name='crashreport',
- name='device',
- field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='crashreports.Device'),
+ model_name="crashreport",
+ name="device",
+ field=models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ to="crashreports.Device",
+ ),
),
migrations.AddField(
- model_name='crashreport',
- name='tags',
- field=taggit.managers.TaggableManager(blank=True, help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'),
+ model_name="crashreport",
+ name="tags",
+ field=taggit.managers.TaggableManager(
+ blank=True,
+ help_text="A comma-separated list of tags.",
+ through="taggit.TaggedItem",
+ to="taggit.Tag",
+ verbose_name="Tags",
+ ),
),
]
diff --git a/crashreports/migrations/0002_auto_20170502_1155.py b/crashreports/migrations/0002_auto_20170502_1155.py
index 38ee8db..e6e520c 100644
--- a/crashreports/migrations/0002_auto_20170502_1155.py
+++ b/crashreports/migrations/0002_auto_20170502_1155.py
@@ -9,64 +9,80 @@
class Migration(migrations.Migration):
- dependencies = [
- ('crashreports', '0001_initial'),
- ]
+ dependencies = [("crashreports", "0001_initial")]
operations = [
migrations.AlterField(
- model_name='crashreport',
- name='boot_reason',
+ model_name="crashreport",
+ name="boot_reason",
field=models.CharField(db_index=True, max_length=200),
),
migrations.AlterField(
- model_name='crashreport',
- name='build_fingerprint',
+ model_name="crashreport",
+ name="build_fingerprint",
field=models.CharField(db_index=True, max_length=200),
),
migrations.AlterField(
- model_name='crashreport',
- name='date',
+ model_name="crashreport",
+ name="date",
field=models.DateTimeField(db_index=True),
),
migrations.AlterField(
- model_name='crashreport',
- name='device',
- field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='crashreports', to='crashreports.Device'),
+ model_name="crashreport",
+ name="device",
+ field=models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name="crashreports",
+ to="crashreports.Device",
+ ),
),
migrations.AlterField(
- model_name='crashreport',
- name='power_off_reason',
+ model_name="crashreport",
+ name="power_off_reason",
field=models.CharField(db_index=True, max_length=200),
),
migrations.AlterField(
- model_name='crashreport',
- name='power_on_reason',
+ model_name="crashreport",
+ name="power_on_reason",
field=models.CharField(db_index=True, max_length=200),
),
migrations.AlterField(
- model_name='device',
- name='uuid',
- field=models.CharField(db_index=True, default=uuid.uuid4, editable=False, max_length=64, unique=True),
+ model_name="device",
+ name="uuid",
+ field=models.CharField(
+ db_index=True,
+ default=uuid.uuid4,
+ editable=False,
+ max_length=64,
+ unique=True,
+ ),
),
migrations.AlterField(
- model_name='heartbeat',
- name='build_fingerprint',
+ model_name="heartbeat",
+ name="build_fingerprint",
field=models.CharField(db_index=True, max_length=200),
),
migrations.AlterField(
- model_name='heartbeat',
- name='date',
+ model_name="heartbeat",
+ name="date",
field=models.DateTimeField(db_index=True),
),
migrations.AlterField(
- model_name='heartbeat',
- name='device',
- field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='heartbeats', to='crashreports.Device'),
+ model_name="heartbeat",
+ name="device",
+ field=models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name="heartbeats",
+ to="crashreports.Device",
+ ),
),
migrations.AlterField(
- model_name='logfile',
- name='crashreport',
- field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='logfiles', to='crashreports.Crashreport'),
+ model_name="logfile",
+ name="crashreport",
+ field=models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name="logfiles",
+ to="crashreports.Crashreport",
+ ),
),
]
diff --git a/crashreports/migrations/0003_crashreport_and_heartbeat_with_radio_version.py b/crashreports/migrations/0003_crashreport_and_heartbeat_with_radio_version.py
index 564cc0e..403593e 100644
--- a/crashreports/migrations/0003_crashreport_and_heartbeat_with_radio_version.py
+++ b/crashreports/migrations/0003_crashreport_and_heartbeat_with_radio_version.py
@@ -8,19 +8,17 @@
class Migration(migrations.Migration):
- dependencies = [
- ('crashreports', '0002_auto_20170502_1155'),
- ]
+ dependencies = [("crashreports", "0002_auto_20170502_1155")]
operations = [
migrations.AddField(
- model_name='crashreport',
- name='radio_version',
+ model_name="crashreport",
+ name="radio_version",
field=models.CharField(db_index=True, max_length=200, null=True),
),
migrations.AddField(
- model_name='heartbeat',
- name='radio_version',
+ model_name="heartbeat",
+ name="radio_version",
field=models.CharField(db_index=True, max_length=200, null=True),
),
]
diff --git a/crashreports/models.py b/crashreports/models.py
index 6bf6056..5120322 100644
--- a/crashreports/models.py
+++ b/crashreports/models.py
@@ -9,14 +9,23 @@
class Device(models.Model):
- def __str__( self ):
+ def __str__(self):
return self.uuid
+
# for every device there is a django user
- uuid = models.CharField( db_index=True,max_length=64, unique=True,
- default=uuid.uuid4, editable=False)
+ uuid = models.CharField(
+ db_index=True,
+ max_length=64,
+ unique=True,
+ default=uuid.uuid4,
+ editable=False,
+ )
user = models.OneToOneField(
- User, related_name='Hiccup_Device', on_delete=models.CASCADE,
- unique=True)
+ User,
+ related_name="Hiccup_Device",
+ on_delete=models.CASCADE,
+ unique=True,
+ )
imei = models.CharField(max_length=32, null=True, blank=True)
board_date = models.DateTimeField(null=True, blank=True)
chipset = models.CharField(max_length=200, null=True, blank=True)
@@ -42,27 +51,30 @@
def crashreport_file_name(instance, filename):
- return '/'.join([
- "crashreport_uploads",
- instance.crashreport.device.uuid,
- str(instance.crashreport.id),
- str(instance.crashreport.date),
- filename])
+ return "/".join(
+ [
+ "crashreport_uploads",
+ instance.crashreport.device.uuid,
+ str(instance.crashreport.id),
+ str(instance.crashreport.date),
+ filename,
+ ]
+ )
class Crashreport(models.Model):
- BOOT_REASON_UNKOWN = 'UNKNOWN'
- BOOT_REASON_KEYBOARD_POWER_ON = 'keyboard power on'
- BOOT_REASON_RTC_ALARM = 'RTC alarm'
- CRASH_BOOT_REASONS = [
- BOOT_REASON_UNKOWN,
- BOOT_REASON_KEYBOARD_POWER_ON,
- ]
- SMPL_BOOT_REASONS = [
- BOOT_REASON_RTC_ALARM,
- ]
+ BOOT_REASON_UNKOWN = "UNKNOWN"
+ BOOT_REASON_KEYBOARD_POWER_ON = "keyboard power on"
+ BOOT_REASON_RTC_ALARM = "RTC alarm"
+ CRASH_BOOT_REASONS = [BOOT_REASON_UNKOWN, BOOT_REASON_KEYBOARD_POWER_ON]
+ SMPL_BOOT_REASONS = [BOOT_REASON_RTC_ALARM]
- device = models.ForeignKey(Device, db_index=True, related_name='crashreports', on_delete=models.CASCADE)
+ device = models.ForeignKey(
+ Device,
+ db_index=True,
+ related_name="crashreports",
+ on_delete=models.CASCADE,
+ )
is_fake_report = models.BooleanField(default=False)
app_version = models.IntegerField()
uptime = models.CharField(max_length=200)
@@ -92,12 +104,16 @@
def _get_uuid(self):
"Returns the person's full name."
return self.device.uuid
+
uuid = property(_get_uuid)
-#TODO remove logfile_type or make it meaningful
+
+# TODO remove logfile_type or make it meaningful
class LogFile(models.Model):
logfile_type = models.TextField(max_length=36, default="last_kmsg")
- crashreport = models.ForeignKey(Crashreport,related_name='logfiles', on_delete=models.CASCADE)
+ crashreport = models.ForeignKey(
+ Crashreport, related_name="logfiles", on_delete=models.CASCADE
+ )
logfile = models.FileField(upload_to=crashreport_file_name, max_length=500)
crashreport_local_id = models.PositiveIntegerField(blank=True)
created_at = models.DateTimeField(auto_now_add=True)
@@ -109,13 +125,15 @@
class HeartBeat(models.Model):
- device = models.ForeignKey(Device,
+ device = models.ForeignKey(
+ Device,
db_index=True,
- related_name='heartbeats',
- on_delete=models.CASCADE)
+ related_name="heartbeats",
+ on_delete=models.CASCADE,
+ )
app_version = models.IntegerField()
uptime = models.CharField(max_length=200)
- build_fingerprint = models.CharField( db_index=True, max_length=200)
+ build_fingerprint = models.CharField(db_index=True, max_length=200)
radio_version = models.CharField(db_index=True, max_length=200, null=True)
date = models.DateTimeField(db_index=True)
device_local_id = models.PositiveIntegerField(blank=True)
@@ -129,4 +147,5 @@
def _get_uuid(self):
"Returns the person's full name."
return self.device.uuid
+
uuid = property(_get_uuid)
diff --git a/crashreports/permissions.py b/crashreports/permissions.py
index ff79149..c1efe79 100644
--- a/crashreports/permissions.py
+++ b/crashreports/permissions.py
@@ -7,42 +7,49 @@
device = Device.objects.get(user=user)
except:
return False
- if (uuid == device.uuid):
+ if uuid == device.uuid:
return True
return False
def user_is_hiccup_staff(user):
- if (user.groups.filter(name='FairphoneSoftwareTeam').exists()):
+ if user.groups.filter(name="FairphoneSoftwareTeam").exists():
return True
else:
- return user.has_perms([
- # Crashreports
- 'crashreports.add_crashreport', 'crashreports.change_crashreport',
- 'crashreports.del_crashreport',
- # Heartbeats
- 'heartbeat.add_crashreport', 'heartbeat.change_crashreport',
- 'heartbeat.del_crashreport',
- # Logfiles
- 'heartbeat.add_logfile', 'heartbeat.change_logfile',
- 'heartbeat.del_logfile',
- ])
+ return user.has_perms(
+ [
+ # Crashreports
+ "crashreports.add_crashreport",
+ "crashreports.change_crashreport",
+ "crashreports.del_crashreport",
+ # Heartbeats
+ "heartbeat.add_crashreport",
+ "heartbeat.change_crashreport",
+ "heartbeat.del_crashreport",
+ # Logfiles
+ "heartbeat.add_logfile",
+ "heartbeat.change_logfile",
+ "heartbeat.del_logfile",
+ ]
+ )
+
class HasStatsAccess(BasePermission):
def has_permission(self, request, view):
return user_is_hiccup_staff(request.user)
+
class HasRightsOrIsDeviceOwnerDeviceCreation(BasePermission):
def has_permission(self, request, view):
- if (user_is_hiccup_staff(request.user)):
+ if user_is_hiccup_staff(request.user):
return True
# special case:
# user is the owner of a device. in this case creations are allowed.
# we have to check if the device with the supplied uuid indeed
# belongs to the user
- if request.method == 'POST':
- if ('uuid' not in request.data):
+ if request.method == "POST":
+ if "uuid" not in request.data:
return False
return user_owns_uuid(request.user, request.data["uuid"])
return False
diff --git a/crashreports/rest_api_crashreports.py b/crashreports/rest_api_crashreports.py
index b6555fd..df99732 100644
--- a/crashreports/rest_api_crashreports.py
+++ b/crashreports/rest_api_crashreports.py
@@ -10,31 +10,32 @@
class ListCreateView(generics.ListCreateAPIView):
queryset = Crashreport.objects.all()
paginate_by = 20
- permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation, )
+ permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation,)
serializer_class = CrashReportSerializer
- filter_fields = ('device', 'build_fingerprint', 'radio_version')
+ filter_fields = ("device", "build_fingerprint", "radio_version")
pass
def dispatch(self, *args, **kwargs):
- if 'uuid' in kwargs:
+ if "uuid" in kwargs:
self.queryset = Crashreport.objects.filter(
- device__uuid=kwargs['uuid'])
+ device__uuid=kwargs["uuid"]
+ )
return generics.ListCreateAPIView.dispatch(self, *args, **kwargs)
def perform_create(self, serializer):
serializer.save()
return Response(
- {
- 'device_local_id': serializer.data['device_local_id']
- }, status.HTTP_200_OK)
+ {"device_local_id": serializer.data["device_local_id"]},
+ status.HTTP_200_OK,
+ )
class RetrieveUpdateDestroyView(generics.RetrieveUpdateDestroyAPIView):
queryset = Crashreport.objects.all()
- permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation, )
+ permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation,)
serializer_class = CrashReportSerializer
- multiple_lookup_fields = {'id', 'device__uuid', 'device_local_id'}
+ multiple_lookup_fields = {"id", "device__uuid", "device_local_id"}
def get_object(self):
queryset = self.get_queryset()
diff --git a/crashreports/rest_api_devices.py b/crashreports/rest_api_devices.py
index 17e0d77..96923b2 100644
--- a/crashreports/rest_api_devices.py
+++ b/crashreports/rest_api_devices.py
@@ -17,42 +17,64 @@
from crashreports.response_descriptions import default_desc
-@method_decorator(name='get', decorator=swagger_auto_schema(
- operation_description='List devices'))
-@method_decorator(name='post', decorator=swagger_auto_schema(
- operation_description='Create a device',
- responses=dict([default_desc(ValidationError)])))
+@method_decorator(
+ name="get",
+ decorator=swagger_auto_schema(operation_description="List devices"),
+)
+@method_decorator(
+ name="post",
+ decorator=swagger_auto_schema(
+ operation_description="Create a device",
+ responses=dict([default_desc(ValidationError)]),
+ ),
+)
class ListCreateDevices(generics.ListCreateAPIView):
"""Endpoint for listing devices and creating new devices."""
queryset = Device.objects.all()
paginate_by = 20
- permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation, )
+ permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation,)
serializer_class = DeviceSerializer
- filter_fields = ('uuid', 'board_date', 'chipset')
+ filter_fields = ("uuid", "board_date", "chipset")
-@method_decorator(name='get', decorator=swagger_auto_schema(
- operation_description='Get a device',
- responses=dict([default_desc(NotFound)])))
-@method_decorator(name='put', decorator=swagger_auto_schema(
- operation_description='Update a device',
- responses=dict([default_desc(NotFound), default_desc(ValidationError)])))
-@method_decorator(name='patch', decorator=swagger_auto_schema(
- operation_description='Make a partial update for a device',
- responses=dict([default_desc(NotFound), default_desc(ValidationError)])))
-@method_decorator(name='delete', decorator=swagger_auto_schema(
- operation_description='Delete a device',
- responses=dict([default_desc(NotFound)])))
+@method_decorator(
+ name="get",
+ decorator=swagger_auto_schema(
+ operation_description="Get a device",
+ responses=dict([default_desc(NotFound)]),
+ ),
+)
+@method_decorator(
+ name="put",
+ decorator=swagger_auto_schema(
+ operation_description="Update a device",
+ responses=dict([default_desc(NotFound), default_desc(ValidationError)]),
+ ),
+)
+@method_decorator(
+ name="patch",
+ decorator=swagger_auto_schema(
+ operation_description="Make a partial update for a device",
+ responses=dict([default_desc(NotFound), default_desc(ValidationError)]),
+ ),
+)
+@method_decorator(
+ name="delete",
+ decorator=swagger_auto_schema(
+ operation_description="Delete a device",
+ responses=dict([default_desc(NotFound)]),
+ ),
+)
class RetrieveUpdateDestroyDevice(generics.RetrieveUpdateDestroyAPIView):
"""Endpoint for retrieving, updating, patching and deleting devices."""
# pylint: disable=too-many-ancestors
queryset = Device.objects.all()
- permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation, )
+ permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation,)
serializer_class = DeviceSerializer
- lookup_field = 'uuid'
+ lookup_field = "uuid"
class DeviceRegisterResponseSchema(DeviceSerializer):
@@ -60,19 +82,26 @@
class Meta: # noqa: D106
model = Device
- fields = ['uuid', 'token']
+ fields = ["uuid", "token"]
@swagger_auto_schema(
- method='post',
+ method="post",
request_body=DeviceCreateSerializer,
- responses=dict([
- default_desc(ValidationError),
- (status.HTTP_200_OK,
- openapi.Response('The device has been successfully registered.',
- DeviceRegisterResponseSchema))
- ]))
-@api_view(http_method_names=['POST'], )
+ responses=dict(
+ [
+ default_desc(ValidationError),
+ (
+ status.HTTP_200_OK,
+ openapi.Response(
+ "The device has been successfully registered.",
+ DeviceRegisterResponseSchema,
+ ),
+ ),
+ ]
+ ),
+)
+@api_view(http_method_names=["POST"])
@permission_classes((AllowAny,))
def register_device(request):
"""Register a new device.
@@ -84,13 +113,13 @@
serializer = DeviceCreateSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
device = Device()
- user = User.objects.create_user("device_" + str(device.uuid), '', None)
- permission = Permission.objects.get(name='Can add crashreport')
+ user = User.objects.create_user("device_" + str(device.uuid), "", None)
+ permission = Permission.objects.get(name="Can add crashreport")
user.user_permissions.add(permission)
user.save()
- device.board_date = serializer.validated_data['board_date']
- device.chipset = serializer.validated_data['chipset']
+ device.board_date = serializer.validated_data["board_date"]
+ device.chipset = serializer.validated_data["chipset"]
device.user = user
device.token = Token.objects.create(user=user).key
device.save()
- return Response({'uuid': device.uuid, 'token': device.token})
+ return Response({"uuid": device.uuid, "token": device.token})
diff --git a/crashreports/rest_api_heartbeats.py b/crashreports/rest_api_heartbeats.py
index 841dec8..f2e19db 100644
--- a/crashreports/rest_api_heartbeats.py
+++ b/crashreports/rest_api_heartbeats.py
@@ -11,23 +11,23 @@
class ListCreateView(generics.ListCreateAPIView):
queryset = HeartBeat.objects.all()
paginate_by = 20
- permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation, )
+ permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation,)
serializer_class = HeartBeatSerializer
- filter_fields = ('device', 'build_fingerprint', 'radio_version')
-
+ filter_fields = ("device", "build_fingerprint", "radio_version")
def get(self, *args, **kwargs):
- if 'uuid' in kwargs:
+ if "uuid" in kwargs:
self.queryset = HeartBeat.objects.filter(
- device__uuid=kwargs['uuid'])
+ device__uuid=kwargs["uuid"]
+ )
return generics.ListCreateAPIView.get(self, *args, **kwargs)
class RetrieveUpdateDestroyView(generics.RetrieveUpdateDestroyAPIView):
queryset = HeartBeat.objects.all()
- permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation, )
+ permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation,)
serializer_class = HeartBeatSerializer
- multiple_lookup_fields = {'id', 'device__uuid', 'device_local_id'}
+ multiple_lookup_fields = {"id", "device__uuid", "device_local_id"}
def get_object(self):
queryset = self.get_queryset()
diff --git a/crashreports/rest_api_logfiles.py b/crashreports/rest_api_logfiles.py
index 7e02dab..df3bbcb 100644
--- a/crashreports/rest_api_logfiles.py
+++ b/crashreports/rest_api_logfiles.py
@@ -21,28 +21,31 @@
class ListCreateView(generics.ListAPIView):
queryset = LogFile.objects.all()
- permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation, )
+ permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation,)
serializer_class = LogFileSerializer
class RetrieveUpdateDestroyView(generics.RetrieveUpdateDestroyAPIView):
queryset = LogFile.objects.all()
- permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation, )
+ permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation,)
serializer_class = LogFileSerializer
-@api_view(http_method_names=['POST'], )
-@parser_classes([FileUploadParser, ])
-@permission_classes([IsAuthenticated, ])
+@api_view(http_method_names=["POST"])
+@parser_classes([FileUploadParser])
+@permission_classes([IsAuthenticated])
def logfile_put(request, uuid, device_local_id, filename):
try:
- crashreport = Crashreport.objects.get(device__uuid=uuid,
- device_local_id=device_local_id)
+ crashreport = Crashreport.objects.get(
+ device__uuid=uuid, device_local_id=device_local_id
+ )
except:
raise NotFound(detail="Crashreport does not exist.")
- if (not (user_owns_uuid(request.user, crashreport.device.uuid)
- or user_is_hiccup_staff(request.user))):
+ if not (
+ user_owns_uuid(request.user, crashreport.device.uuid)
+ or user_is_hiccup_staff(request.user)
+ ):
raise PermissionDenied(detail="Not allowed.")
f = request.data["file"]
logfile = LogFile(crashreport=crashreport, logfile=f)
diff --git a/crashreports/serializers.py b/crashreports/serializers.py
index 732e595..af71a70 100644
--- a/crashreports/serializers.py
+++ b/crashreports/serializers.py
@@ -5,9 +5,7 @@
from rest_framework.exceptions import NotFound
from rest_framework import permissions
-from crashreports.models import (
- Crashreport, Device, HeartBeat, LogFile
-)
+from crashreports.models import Crashreport, Device, HeartBeat, LogFile
from crashreports.permissions import user_is_hiccup_staff
@@ -23,7 +21,7 @@
Given the *outgoing* object instance, return the primitive value
that should be used for this field.
"""
- if user_is_hiccup_staff(self.context['request'].user):
+ if user_is_hiccup_staff(self.context["request"].user):
return super(PrivateField, self).get_attribute(instance)
return -1
@@ -33,10 +31,8 @@
permission_classes = (permissions.AllowAny,)
logfiles = serializers.HyperlinkedRelatedField(
- read_only=True,
- many=True,
- view_name='api_v1_logfiles_by_id',
- )
+ read_only=True, many=True, view_name="api_v1_logfiles_by_id"
+ )
uuid = serializers.CharField(max_length=64)
id = PrivateField()
device_local_id = serializers.IntegerField(required=False)
@@ -44,7 +40,7 @@
class Meta: # noqa: D106
model = Crashreport
- exclude = ('device',)
+ exclude = ("device",)
def create(self, validated_data):
"""Create a crashreport.
@@ -56,10 +52,10 @@
"""
try:
- device = Device.objects.get(uuid=validated_data['uuid'])
+ device = Device.objects.get(uuid=validated_data["uuid"])
except ObjectDoesNotExist:
raise NotFound(detail="uuid does not exist")
- validated_data.pop('uuid', None)
+ validated_data.pop("uuid", None)
report = Crashreport(**validated_data)
report.device = device
report.save()
@@ -77,7 +73,7 @@
class Meta: # noqa: D106
model = HeartBeat
- exclude = ('device',)
+ exclude = ("device",)
def create(self, validated_data):
"""Create a heartbeat report.
@@ -89,10 +85,10 @@
"""
try:
- device = Device.objects.get(uuid=validated_data['uuid'])
+ device = Device.objects.get(uuid=validated_data["uuid"])
except ObjectDoesNotExist:
raise NotFound(detail="uuid does not exist")
- validated_data.pop('uuid', None)
+ validated_data.pop("uuid", None)
heartbeat = HeartBeat(**validated_data)
heartbeat.device = device
heartbeat.save()
@@ -106,7 +102,7 @@
class Meta: # noqa: D106
model = LogFile
- fields = '__all__'
+ fields = "__all__"
class DeviceSerializer(serializers.ModelSerializer):
@@ -118,7 +114,7 @@
class Meta: # noqa: D106
model = Device
- fields = '__all__'
+ fields = "__all__"
class DeviceCreateSerializer(DeviceSerializer):
@@ -126,8 +122,8 @@
class Meta: # noqa: D106
model = Device
- fields = ('board_date', 'chipset')
+ fields = ("board_date", "chipset")
extra_kwargs = {
- 'board_date': {'required': True},
- 'chipset': {'required': True},
+ "board_date": {"required": True},
+ "chipset": {"required": True},
}
diff --git a/crashreports/tests.py b/crashreports/tests.py
index 2267a79..354b330 100644
--- a/crashreports/tests.py
+++ b/crashreports/tests.py
@@ -30,42 +30,47 @@
crash_type: The invalid crash type.
"""
super(InvalidCrashTypeError, self).__init__(
- '{} is not a valid crash type'.format(crash_type))
+ "{} is not a valid crash type".format(crash_type)
+ )
-class Dummy():
+class Dummy:
"""Dummy values for devices, heartbeats and crashreports."""
DEFAULT_DUMMY_DEVICE_REGISTER_VALUES = {
- 'board_date': '2015-12-15T01:23:45Z',
- 'chipset': 'Qualcomm MSM8974PRO-AA',
+ "board_date": "2015-12-15T01:23:45Z",
+ "chipset": "Qualcomm MSM8974PRO-AA",
}
DEFAULT_DUMMY_HEARTBEAT_VALUES = {
- 'uuid': None,
- 'app_version': 10100,
- 'uptime': (
- 'up time: 16 days, 21:49:56, idle time: 5 days, 20:55:04, '
- 'sleep time: 10 days, 20:46:27'),
- 'build_fingerprint': (
- 'Fairphone/FP2/FP2:6.0.1/FP2-gms-18.03.1/FP2-gms-18.03.1:user/'
- 'release-keys'),
- 'radio_version': '4437.1-FP2-0-08',
- 'date': '2018-03-19T09:58:30.386Z',
+ "uuid": None,
+ "app_version": 10100,
+ "uptime": (
+ "up time: 16 days, 21:49:56, idle time: 5 days, 20:55:04, "
+ "sleep time: 10 days, 20:46:27"
+ ),
+ "build_fingerprint": (
+ "Fairphone/FP2/FP2:6.0.1/FP2-gms-18.03.1/FP2-gms-18.03.1:user/"
+ "release-keys"
+ ),
+ "radio_version": "4437.1-FP2-0-08",
+ "date": "2018-03-19T09:58:30.386Z",
}
DEFAULT_DUMMY_CRASHREPORTS_VALUES = DEFAULT_DUMMY_HEARTBEAT_VALUES.copy()
- DEFAULT_DUMMY_CRASHREPORTS_VALUES.update({
- 'is_fake_report': 0,
- 'boot_reason': 'why?',
- 'power_on_reason': 'it was powered on',
- 'power_off_reason': 'something happened and it went off',
- })
+ DEFAULT_DUMMY_CRASHREPORTS_VALUES.update(
+ {
+ "is_fake_report": 0,
+ "boot_reason": "why?",
+ "power_on_reason": "it was powered on",
+ "power_off_reason": "something happened and it went off",
+ }
+ )
CRASH_TYPE_TO_BOOT_REASON_MAP = {
- 'crash': Crashreport.BOOT_REASON_KEYBOARD_POWER_ON,
- 'smpl': Crashreport.BOOT_REASON_RTC_ALARM,
- 'other': 'whatever',
+ "crash": Crashreport.BOOT_REASON_KEYBOARD_POWER_ON,
+ "smpl": Crashreport.BOOT_REASON_RTC_ALARM,
+ "other": "whatever",
}
@staticmethod
@@ -83,7 +88,8 @@
from `Dummy.DEFAULT_DUMMY_DEVICE_REGISTER_VALUES`.
"""
return Dummy._update_copy(
- Dummy.DEFAULT_DUMMY_DEVICE_REGISTER_VALUES, kwargs)
+ Dummy.DEFAULT_DUMMY_DEVICE_REGISTER_VALUES, kwargs
+ )
@staticmethod
def heartbeat_data(**kwargs):
@@ -108,12 +114,14 @@
keyword arguments already.
"""
data = Dummy._update_copy(
- Dummy.DEFAULT_DUMMY_CRASHREPORTS_VALUES, kwargs)
- if report_type and 'boot_reason' not in kwargs:
+ Dummy.DEFAULT_DUMMY_CRASHREPORTS_VALUES, kwargs
+ )
+ if report_type and "boot_reason" not in kwargs:
if report_type not in Dummy.CRASH_TYPE_TO_BOOT_REASON_MAP:
raise InvalidCrashTypeError(report_type)
- data['boot_reason'] = Dummy.CRASH_TYPE_TO_BOOT_REASON_MAP.get(
- report_type)
+ data["boot_reason"] = Dummy.CRASH_TYPE_TO_BOOT_REASON_MAP.get(
+ report_type
+ )
return data
@@ -129,7 +137,8 @@
server is stored in self.admin.
"""
admin_user = User.objects.create_superuser(
- 'somebody', 'somebody@example.com', 'thepassword')
+ "somebody", "somebody@example.com", "thepassword"
+ )
self.admin = APIClient()
self.admin.force_authenticate(admin_user)
@@ -148,10 +157,10 @@
response = self.client.post(reverse(self.REGISTER_DEVICE_URL), data)
self.assertEqual(response.status_code, status.HTTP_200_OK)
- uuid = response.data['uuid']
- token = response.data['token']
+ uuid = response.data["uuid"]
+ token = response.data["token"]
user = APIClient()
- user.credentials(HTTP_AUTHORIZATION='Token ' + token)
+ user.credentials(HTTP_AUTHORIZATION="Token " + token)
return uuid, user, token
@@ -161,8 +170,9 @@
def test_register(self):
"""Test registration of devices."""
- response = self.client.post(reverse(self.REGISTER_DEVICE_URL),
- Dummy.device_register_data())
+ response = self.client.post(
+ reverse(self.REGISTER_DEVICE_URL), Dummy.device_register_data()
+ )
self.assertTrue("token" in response.data)
self.assertTrue("uuid" in response.data)
self.assertEqual(response.status_code, status.HTTP_200_OK)
@@ -175,21 +185,21 @@
def test_create_missing_board_date(self):
"""Test registration with missing board date."""
data = Dummy.device_register_data()
- data.pop('board_date')
+ data.pop("board_date")
response = self.client.post(reverse(self.REGISTER_DEVICE_URL), data)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
def test_create_missing_chipset(self):
"""Test registration with missing chipset."""
data = Dummy.device_register_data()
- data.pop('chipset')
+ data.pop("chipset")
response = self.client.post(reverse(self.REGISTER_DEVICE_URL), data)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
def test_create_invalid_board_date(self):
"""Test registration with invalid board date."""
data = Dummy.device_register_data()
- data['board_date'] = 'not_a_valid_date'
+ data["board_date"] = "not_a_valid_date"
response = self.client.post(reverse(self.REGISTER_DEVICE_URL), data)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
@@ -204,7 +214,7 @@
data = Dummy.device_register_data()
# In 2017, the Netherlands changed from CET to CEST on March,
# 26 at 02:00
- data['board_date'] = '2017-03-26 02:34:56'
+ data["board_date"] = "2017-03-26 02:34:56"
response = self.client.post(reverse(self.REGISTER_DEVICE_URL), data)
self.assertEqual(response.status_code, status.HTTP_200_OK)
@@ -219,7 +229,7 @@
data = Dummy.device_register_data()
# In 2017, the Netherlands changed from CEST to CET on October,
# 29 at 03:00
- data['board_date'] = '2017-10-29 02:34:56'
+ data["board_date"] = "2017-10-29 02:34:56"
response = self.client.post(reverse(self.REGISTER_DEVICE_URL), data)
self.assertEqual(response.status_code, status.HTTP_200_OK)
@@ -234,15 +244,14 @@
"""Test registration of 2 devices."""
number_of_devices = 2
uuids = [
- str(self._register_device()[0])
- for _ in range(number_of_devices)
+ str(self._register_device()[0]) for _ in range(number_of_devices)
]
response = self.admin.get(reverse(self.LIST_CREATE_URL), {})
self.assertEqual(response.status_code, status.HTTP_200_OK)
- self.assertEqual(len(response.data['results']), number_of_devices)
- for result in response.data['results']:
- self.assertIn(result['uuid'], uuids)
+ self.assertEqual(len(response.data["results"]), number_of_devices)
+ for result in response.data["results"]:
+ self.assertIn(result["uuid"], uuids)
def test_device_list_unauth(self):
"""Test listing devices without authentication."""
@@ -254,8 +263,8 @@
uuid, _, token = self._register_device()
response = self.admin.get(reverse(self.RETRIEVE_URL, args=[uuid]), {})
self.assertEqual(response.status_code, status.HTTP_200_OK)
- self.assertEqual(response.data['uuid'], str(uuid))
- self.assertEqual(response.data['token'], token)
+ self.assertEqual(response.data["uuid"], str(uuid))
+ self.assertEqual(response.data["token"], token)
def test_retrieve_device_unauth(self):
"""Test retrieval of devices without authentication."""
@@ -288,14 +297,15 @@
def _post_multiple(self, client, data, count):
return [
client.post(reverse(self.LIST_CREATE_URL), data)
- for _ in range(count)]
+ for _ in range(count)
+ ]
def _retrieve_single(self, user):
count = 5
response = self._post_multiple(self.admin, self.data, count)
self.assertEqual(len(response), count)
self.assertEqual(response[0].status_code, status.HTTP_201_CREATED)
- url = reverse(self.RETRIEVE_URL, args=[response[0].data['id']])
+ url = reverse(self.RETRIEVE_URL, args=[response[0].data["id"]])
request = user.get(url)
return request.status_code
@@ -304,8 +314,10 @@
response = self._post_multiple(self.user, self.data, count)
self.assertEqual(len(response), count)
self.assertEqual(response[0].status_code, status.HTTP_201_CREATED)
- url = reverse(self.RETRIEVE_BY_UUID_URL, args=[
- self.uuid, response[0].data['device_local_id']])
+ url = reverse(
+ self.RETRIEVE_BY_UUID_URL,
+ args=[self.uuid, response[0].data["device_local_id"]],
+ )
request = user.get(url)
return request.status_code
@@ -318,36 +330,37 @@
def test_create_no_auth(self):
"""Test creation without authentication."""
noauth_client = APIClient()
- response = noauth_client.post(
- reverse(self.LIST_CREATE_URL), self.data)
+ response = noauth_client.post(reverse(self.LIST_CREATE_URL), self.data)
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
def test_create_as_admin(self):
"""Test creation as admin."""
response = self.admin.post(reverse(self.LIST_CREATE_URL), self.data)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
- self.assertTrue(response.data['id'] > 0)
+ self.assertTrue(response.data["id"] > 0)
def test_create_as_admin_not_existing_device(self):
"""Test creation of heartbeat on non-existing device."""
response = self.admin.post(
- reverse(self.LIST_CREATE_URL), self._create_dummy_data())
+ reverse(self.LIST_CREATE_URL), self._create_dummy_data()
+ )
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
def test_create_as_uuid_owner(self):
"""Test creation as owner."""
response = self.user.post(
reverse(self.LIST_CREATE_URL),
- self._create_dummy_data(uuid=self.uuid))
+ self._create_dummy_data(uuid=self.uuid),
+ )
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
- self.assertEqual(response.data['id'], -1)
+ self.assertEqual(response.data["id"], -1)
def test_create_as_uuid_not_owner(self):
"""Test creation as non-owner."""
uuid, _, _ = self._register_device()
response = self.user.post(
- reverse(self.LIST_CREATE_URL),
- self._create_dummy_data(uuid=uuid))
+ reverse(self.LIST_CREATE_URL), self._create_dummy_data(uuid=uuid)
+ )
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
def test_list(self):
@@ -356,42 +369,45 @@
self._post_multiple(self.user, self.data, count)
response = self.admin.get(reverse(self.LIST_CREATE_URL))
self.assertEqual(response.status_code, status.HTTP_200_OK)
- self.assertEqual(len(response.data['results']), count)
+ self.assertEqual(len(response.data["results"]), count)
def test_retrieve_single_admin(self):
"""Test retrieval as admin."""
- self.assertEqual(
- self._retrieve_single(self.admin), status.HTTP_200_OK)
+ self.assertEqual(self._retrieve_single(self.admin), status.HTTP_200_OK)
def test_retrieve_single_device_owner(self):
"""Test retrieval as device owner."""
self.assertEqual(
- self._retrieve_single(self.user), status.HTTP_403_FORBIDDEN)
+ self._retrieve_single(self.user), status.HTTP_403_FORBIDDEN
+ )
def test_retrieve_single_noauth(self):
"""Test retrieval without authentication."""
noauth_client = APIClient()
self.assertEqual(
- self._retrieve_single(noauth_client),
- status.HTTP_401_UNAUTHORIZED)
+ self._retrieve_single(noauth_client), status.HTTP_401_UNAUTHORIZED
+ )
def test_retrieve_single_by_device_admin(self):
"""Test retrieval by device as admin."""
self.assertEqual(
- self._retrieve_single_by_device(self.admin), status.HTTP_200_OK)
+ self._retrieve_single_by_device(self.admin), status.HTTP_200_OK
+ )
def test_retrieve_single_by_device_device_owner(self):
"""Test retrieval by device as owner."""
self.assertEqual(
self._retrieve_single_by_device(self.user),
- status.HTTP_403_FORBIDDEN)
+ status.HTTP_403_FORBIDDEN,
+ )
def test_retrieve_single_by_device_noauth(self):
"""Test retrieval by device without authentication."""
noauth_client = APIClient()
self.assertEqual(
self._retrieve_single_by_device(noauth_client),
- status.HTTP_401_UNAUTHORIZED)
+ status.HTTP_401_UNAUTHORIZED,
+ )
def test_list_by_uuid(self):
"""Test listing of devices by UUID."""
@@ -399,11 +415,12 @@
uuid, _, _ = self._register_device()
self._post_multiple(self.user, self.data, count)
self._post_multiple(
- self.admin, self._create_dummy_data(uuid=uuid), count)
+ self.admin, self._create_dummy_data(uuid=uuid), count
+ )
url = reverse(self.LIST_CREATE_BY_UUID_URL, args=[self.uuid])
response = self.admin.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
- self.assertEqual(len(response.data['results']), count)
+ self.assertEqual(len(response.data["results"]), count)
def test_list_noauth(self):
"""Test listing of devices without authentication."""
@@ -423,14 +440,14 @@
def test_no_radio_version(self):
"""Test creation and retrieval without radio version."""
data = self._create_dummy_data(uuid=self.uuid)
- data.pop('radio_version')
+ data.pop("radio_version")
response = self.user.post(reverse(self.LIST_CREATE_URL), data)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
url = reverse(self.LIST_CREATE_BY_UUID_URL, args=[self.uuid])
response = self.admin.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
- self.assertEqual(len(response.data['results']), 1)
- self.assertIsNone(response.data['results'][0]['radio_version'])
+ self.assertEqual(len(response.data["results"]), 1)
+ self.assertIsNone(response.data["results"][0]["radio_version"])
def test_radio_version_field(self):
"""Test retrieval of radio version field."""
@@ -439,9 +456,11 @@
url = reverse(self.LIST_CREATE_BY_UUID_URL, args=[self.uuid])
response = self.admin.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
- self.assertEqual(len(response.data['results']), 1)
- self.assertEqual(response.data['results'][0]['radio_version'],
- self.data['radio_version'])
+ self.assertEqual(len(response.data["results"]), 1)
+ self.assertEqual(
+ response.data["results"][0]["radio_version"],
+ self.data["radio_version"],
+ )
def test_send_non_existent_time(self):
"""Test sending of heartbeat with non existent time.
@@ -453,7 +472,7 @@
data = self._create_dummy_data(uuid=self.uuid)
# In 2017, the Netherlands changed from CET to CEST on March,
# 26 at 02:00
- data['date'] = '2017-03-26 02:34:56'
+ data["date"] = "2017-03-26 02:34:56"
response = self.user.post(reverse(self.LIST_CREATE_URL), data)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
@@ -467,7 +486,7 @@
data = self._create_dummy_data(uuid=self.uuid)
# In 2017, the Netherlands changed from CEST to CET on October,
# 29 at 03:00
- data['date'] = '2017-10-29 02:34:56'
+ data["date"] = "2017-10-29 02:34:56"
response = self.user.post(reverse(self.LIST_CREATE_URL), data)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
@@ -506,8 +525,8 @@
data = Dummy.crashreport_data(uuid=uuid)
response = user.post(reverse(self.LIST_CREATE_URL), data)
self.assertEqual(status.HTTP_201_CREATED, response.status_code)
- self.assertTrue('device_local_id' in response.data)
- device_local_id = response.data['device_local_id']
+ self.assertTrue("device_local_id" in response.data)
+ device_local_id = response.data["device_local_id"]
return device_local_id
@@ -516,13 +535,16 @@
device_local_id = self._upload_crashreport(user, uuid)
# Upload a logfile for the crashreport
- logfile = tempfile.NamedTemporaryFile('w+', suffix=".log", delete=True)
+ logfile = tempfile.NamedTemporaryFile("w+", suffix=".log", delete=True)
logfile.write(u"blihblahblub")
response = user.post(
- reverse(self.PUT_LOGFILE_URL, args=[
- uuid, device_local_id, os.path.basename(logfile.name)
- ]),
- {'file': logfile}, format="multipart")
+ reverse(
+ self.PUT_LOGFILE_URL,
+ args=[uuid, device_local_id, os.path.basename(logfile.name)],
+ ),
+ {"file": logfile},
+ format="multipart",
+ )
self.assertEqual(status.HTTP_201_CREATED, response.status_code)
def test_logfile_upload_as_user(self):
diff --git a/crashreports/urls.py b/crashreports/urls.py
index d86c976..b876aaf 100644
--- a/crashreports/urls.py
+++ b/crashreports/urls.py
@@ -7,54 +7,80 @@
urlpatterns = [
# crashreports
- url(r'^api/v1/crashreports/$',
+ url(
+ r"^api/v1/crashreports/$",
rest_api_crashreports.ListCreateView.as_view(),
- name='api_v1_crashreports'),
- url(r'^api/v1/devices/(?P<uuid>[a-f0-9-]+)/crashreports/$',
+ name="api_v1_crashreports",
+ ),
+ url(
+ r"^api/v1/devices/(?P<uuid>[a-f0-9-]+)/crashreports/$",
rest_api_crashreports.ListCreateView.as_view(),
- name='api_v1_crashreports_by_uuid'),
- url(r'^api/v1/crashreports/(?P<id>[0-9]+)/$',
+ name="api_v1_crashreports_by_uuid",
+ ),
+ url(
+ r"^api/v1/crashreports/(?P<id>[0-9]+)/$",
rest_api_crashreports.RetrieveUpdateDestroyView.as_view(),
- name='api_v1_crashreport'),
- url(r'^api/v1/devices/(?P<device__uuid>[a-f0-9-]+)/crashreports/' +
- '(?P<device_local_id>[0-9]+)/$',
+ name="api_v1_crashreport",
+ ),
+ url(
+ r"^api/v1/devices/(?P<device__uuid>[a-f0-9-]+)/crashreports/"
+ + "(?P<device_local_id>[0-9]+)/$",
rest_api_crashreports.RetrieveUpdateDestroyView.as_view(),
- name='api_v1_crashreport_by_uuid'),
-
+ name="api_v1_crashreport_by_uuid",
+ ),
# logfiles
- url(r'^api/v1/devices/(?P<uuid>[a-f0-9-]+)/crashreports/' +
- '(?P<device_local_id>[0-9]+)/logfile_put/(?P<filename>[^/]+)/$',
+ url(
+ r"^api/v1/devices/(?P<uuid>[a-f0-9-]+)/crashreports/"
+ + "(?P<device_local_id>[0-9]+)/logfile_put/(?P<filename>[^/]+)/$",
rest_api_logfiles.logfile_put,
- name='api_v1_putlogfile_for_device_id'),
-
- url(r'^api/v1/logfiles/$',
- rest_api_logfiles.ListCreateView.as_view(),
- name='api_v1_logfiles'),
- url(r'^api/v1/logfiles/(?P<pk>[0-9]+)/$',
+ name="api_v1_putlogfile_for_device_id",
+ ),
+ url(
+ r"^api/v1/logfiles/$",
+ rest_api_logfiles.ListCreateView.as_view(),
+ name="api_v1_logfiles",
+ ),
+ url(
+ r"^api/v1/logfiles/(?P<pk>[0-9]+)/$",
rest_api_logfiles.RetrieveUpdateDestroyView.as_view(),
- name='api_v1_logfiles_by_id'),
-
+ name="api_v1_logfiles_by_id",
+ ),
# heartbeats
- url(r'^api/v1/heartbeats/$',
+ url(
+ r"^api/v1/heartbeats/$",
rest_api_heartbeats.ListCreateView.as_view(),
- name='api_v1_heartbeats'),
- url(r'^api/v1/devices/(?P<uuid>[a-f0-9-]+)/heartbeats/$',
+ name="api_v1_heartbeats",
+ ),
+ url(
+ r"^api/v1/devices/(?P<uuid>[a-f0-9-]+)/heartbeats/$",
rest_api_heartbeats.ListCreateView.as_view(),
- name='api_v1_heartbeats_by_uuid'),
- url(r'^api/v1/heartbeats/(?P<id>[0-9]+)/$',
+ name="api_v1_heartbeats_by_uuid",
+ ),
+ url(
+ r"^api/v1/heartbeats/(?P<id>[0-9]+)/$",
rest_api_heartbeats.RetrieveUpdateDestroyView.as_view(),
- name='api_v1_heartbeat'),
- url(r'^api/v1/devices/(?P<uuid>[a-f0-9-]+)/heartbeats/' +
- '(?P<device_local_id>[0-9]+)/$',
+ name="api_v1_heartbeat",
+ ),
+ url(
+ r"^api/v1/devices/(?P<uuid>[a-f0-9-]+)/heartbeats/"
+ + "(?P<device_local_id>[0-9]+)/$",
rest_api_heartbeats.RetrieveUpdateDestroyView.as_view(),
- name='api_v1_heartbeat_by_uuid'),
-
+ name="api_v1_heartbeat_by_uuid",
+ ),
# devices
- url(r'^api/v1/devices/$', rest_api_devices.ListCreateDevices.as_view(),
- name='api_v1_list_devices'),
- url(r'^api/v1/devices/(?P<uuid>[a-f0-9-]+)/$',
+ url(
+ r"^api/v1/devices/$",
+ rest_api_devices.ListCreateDevices.as_view(),
+ name="api_v1_list_devices",
+ ),
+ url(
+ r"^api/v1/devices/(?P<uuid>[a-f0-9-]+)/$",
rest_api_devices.RetrieveUpdateDestroyDevice.as_view(),
- name='api_v1_retrieve_device'),
- url(r'^api/v1/devices/register/$', rest_api_devices.register_device,
- name='api_v1_register_device'),
+ name="api_v1_retrieve_device",
+ ),
+ url(
+ r"^api/v1/devices/register/$",
+ rest_api_devices.register_device,
+ name="api_v1_register_device",
+ ),
]