Skip to content

Commit 277d690

Browse files
Ken LippoldKen Lippold
authored andcommitted
Updated file attachment services, tests and updated formatting
1 parent 9e8d87f commit 277d690

21 files changed

+419
-206
lines changed

sta/migrations/0001_initial.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,9 @@ class Migration(migrations.Migration):
563563
("name", models.CharField(max_length=255)),
564564
(
565565
"photo",
566-
models.FileField(upload_to=sta.models.thing.thing_file_attachment_storage_path),
566+
models.FileField(
567+
upload_to=sta.models.thing.thing_file_attachment_storage_path
568+
),
567569
),
568570
(
569571
"thing",

sta/migrations/0004_datastreamfileattachmenttype_thingfileattachmenttype_and_more.py

Lines changed: 83 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -10,69 +10,118 @@
1010
class Migration(migrations.Migration):
1111

1212
dependencies = [
13-
('sta', '0003_observation_result_qualifiers_and_more'),
13+
("sta", "0003_observation_result_qualifiers_and_more"),
1414
]
1515

1616
operations = [
1717
migrations.RenameField(
18-
model_name='photo',
19-
old_name='photo',
20-
new_name='file_attachment',
18+
model_name="photo",
19+
old_name="photo",
20+
new_name="file_attachment",
2121
),
2222
migrations.AddField(
23-
model_name='photo',
24-
name='file_attachment_type',
25-
field=models.CharField(default='Photo', max_length=200),
23+
model_name="photo",
24+
name="file_attachment_type",
25+
field=models.CharField(default="Photo", max_length=200),
2626
preserve_default=False,
2727
),
2828
migrations.AlterField(
29-
model_name='photo',
30-
name='thing',
31-
field=models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING,
32-
related_name='thing_file_attachments', to='sta.thing'),
29+
model_name="photo",
30+
name="thing",
31+
field=models.ForeignKey(
32+
on_delete=django.db.models.deletion.DO_NOTHING,
33+
related_name="thing_file_attachments",
34+
to="sta.thing",
35+
),
3336
),
3437
migrations.AlterField(
35-
model_name='tag',
36-
name='thing',
37-
field=models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING,
38-
related_name='thing_tags', to='sta.thing'),
38+
model_name="tag",
39+
name="thing",
40+
field=models.ForeignKey(
41+
on_delete=django.db.models.deletion.DO_NOTHING,
42+
related_name="thing_tags",
43+
to="sta.thing",
44+
),
3945
),
4046
migrations.RenameModel(
41-
old_name='Tag',
42-
new_name='ThingTag',
47+
old_name="Tag",
48+
new_name="ThingTag",
4349
),
4450
migrations.RenameModel(
45-
old_name='Photo',
46-
new_name='ThingFileAttachment',
51+
old_name="Photo",
52+
new_name="ThingFileAttachment",
4753
),
4854
migrations.CreateModel(
49-
name='FileAttachmentType',
55+
name="FileAttachmentType",
5056
fields=[
51-
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
52-
('name', models.CharField(max_length=200, unique=True)),
57+
(
58+
"id",
59+
models.BigAutoField(
60+
auto_created=True,
61+
primary_key=True,
62+
serialize=False,
63+
verbose_name="ID",
64+
),
65+
),
66+
("name", models.CharField(max_length=200, unique=True)),
5367
],
5468
),
5569
migrations.CreateModel(
56-
name='DatastreamFileAttachment',
70+
name="DatastreamFileAttachment",
5771
fields=[
58-
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
59-
('name', models.CharField(max_length=255)),
60-
('file_attachment', models.FileField(upload_to=sta.models.datastream.datastream_file_attachment_storage_path)),
61-
('file_attachment_type', models.CharField(max_length=200)),
62-
('datastream', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='datastream_file_attachments', to='sta.datastream')),
72+
(
73+
"id",
74+
models.BigAutoField(
75+
auto_created=True,
76+
primary_key=True,
77+
serialize=False,
78+
verbose_name="ID",
79+
),
80+
),
81+
("name", models.CharField(max_length=255)),
82+
(
83+
"file_attachment",
84+
models.FileField(
85+
upload_to=sta.models.datastream.datastream_file_attachment_storage_path
86+
),
87+
),
88+
("file_attachment_type", models.CharField(max_length=200)),
89+
(
90+
"datastream",
91+
models.ForeignKey(
92+
on_delete=django.db.models.deletion.DO_NOTHING,
93+
related_name="datastream_file_attachments",
94+
to="sta.datastream",
95+
),
96+
),
6397
],
6498
options={
65-
'unique_together': {('datastream', 'name')},
99+
"unique_together": {("datastream", "name")},
66100
},
67101
bases=(models.Model, iam.models.utils.PermissionChecker),
68102
),
69103
migrations.CreateModel(
70-
name='DatastreamTag',
104+
name="DatastreamTag",
71105
fields=[
72-
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
73-
('key', models.CharField(max_length=255)),
74-
('value', models.CharField(max_length=255)),
75-
('datastream', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='datastream_tags', to='sta.datastream')),
106+
(
107+
"id",
108+
models.BigAutoField(
109+
auto_created=True,
110+
primary_key=True,
111+
serialize=False,
112+
verbose_name="ID",
113+
),
114+
),
115+
("key", models.CharField(max_length=255)),
116+
("value", models.CharField(max_length=255)),
117+
(
118+
"datastream",
119+
models.ForeignKey(
120+
on_delete=django.db.models.deletion.DO_NOTHING,
121+
related_name="datastream_tags",
122+
to="sta.datastream",
123+
),
124+
),
76125
],
77126
bases=(models.Model, iam.models.utils.PermissionChecker),
78127
),

sta/models/__init__.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
from .thing import Thing, ThingTag, ThingFileAttachment, SiteType, SamplingFeatureType, FileAttachmentType
1+
from .thing import (
2+
Thing,
3+
ThingTag,
4+
ThingFileAttachment,
5+
SiteType,
6+
SamplingFeatureType,
7+
FileAttachmentType,
8+
)
29
from .location import Location
310
from .observed_property import ObservedProperty, VariableType
411
from .processing_level import ProcessingLevel

sta/models/datastream.py

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,12 @@ def delete(self, *args, **kwargs):
159159

160160
@staticmethod
161161
def delete_contents(filter_arg: models.Model, filter_suffix: Optional[str]):
162-
from sta.models import Observation, Datastream, DatastreamTag, DatastreamFileAttachment
162+
from sta.models import (
163+
Observation,
164+
Datastream,
165+
DatastreamTag,
166+
DatastreamFileAttachment,
167+
)
163168

164169
datastream_relation_filter = (
165170
f"datastream__{filter_suffix}" if filter_suffix else "datastream"
@@ -175,8 +180,12 @@ def delete_contents(filter_arg: models.Model, filter_suffix: Optional[str]):
175180
**{datastream_relation_filter: filter_arg}
176181
).delete()
177182

178-
DatastreamTag.objects.filter(**{datastream_relation_filter: filter_arg}).delete()
179-
DatastreamFileAttachment.objects.filter(**{datastream_relation_filter: filter_arg}).delete()
183+
DatastreamTag.objects.filter(
184+
**{datastream_relation_filter: filter_arg}
185+
).delete()
186+
DatastreamFileAttachment.objects.filter(
187+
**{datastream_relation_filter: filter_arg}
188+
).delete()
180189

181190

182191
class DatastreamTagQuerySet(models.QuerySet):
@@ -189,7 +198,7 @@ def visible(self, principal: Optional[Union["User", "APIKey"]]):
189198
Q(
190199
datastream__thing__workspace__is_private=False,
191200
datastream__thing__is_private=False,
192-
datastream__is_private=False
201+
datastream__is_private=False,
193202
)
194203
| Q(datastream__thing__workspace__owner=principal)
195204
| Q(
@@ -209,7 +218,7 @@ def visible(self, principal: Optional[Union["User", "APIKey"]]):
209218
Q(
210219
datastream__thing__workspace__is_private=False,
211220
datastream__thing__is_private=False,
212-
datastream__is_private=False
221+
datastream__is_private=False,
213222
)
214223
| Q(
215224
datastream__thing__workspace__apikeys=principal,
@@ -228,13 +237,15 @@ def visible(self, principal: Optional[Union["User", "APIKey"]]):
228237
Q(
229238
datastream__thing__workspace__is_private=False,
230239
datastream__thing__is_private=False,
231-
datastream__is_private=False
240+
datastream__is_private=False,
232241
)
233242
)
234243

235244

236245
class DatastreamTag(models.Model, PermissionChecker):
237-
datastream = models.ForeignKey(Datastream, related_name="datastream_tags", on_delete=models.DO_NOTHING)
246+
datastream = models.ForeignKey(
247+
Datastream, related_name="datastream_tags", on_delete=models.DO_NOTHING
248+
)
238249
key = models.CharField(max_length=255)
239250
value = models.CharField(max_length=255)
240251

@@ -249,9 +260,15 @@ def datastream_file_attachment_storage_path(instance, filename):
249260

250261

251262
class DatastreamFileAttachment(models.Model, PermissionChecker):
252-
datastream = models.ForeignKey(Datastream, related_name="datastream_file_attachments", on_delete=models.DO_NOTHING)
263+
datastream = models.ForeignKey(
264+
Datastream,
265+
related_name="datastream_file_attachments",
266+
on_delete=models.DO_NOTHING,
267+
)
253268
name = models.CharField(max_length=255)
254-
file_attachment = models.FileField(upload_to=datastream_file_attachment_storage_path)
269+
file_attachment = models.FileField(
270+
upload_to=datastream_file_attachment_storage_path
271+
)
255272
file_attachment_type = models.CharField(max_length=200)
256273

257274
def __str__(self):

sta/models/observation.py

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,9 @@ def escape_pg_copy(value):
134134
lines = []
135135
for obs in batch:
136136
line = "\t".join(
137-
escape_pg_copy(getter(obs) if field != "id" else str(obs.id))
137+
escape_pg_copy(
138+
getter(obs) if field != "id" else str(obs.id)
139+
)
138140
for field, getter in zip(db_fields, attr_getters)
139141
)
140142
lines.append(line)
@@ -147,14 +149,24 @@ def escape_pg_copy(value):
147149
if result_qualifiers:
148150
through_model = self.model.result_qualifiers.through
149151
through_table = connection.ops.quote_name(through_model._meta.db_table)
150-
through_columns = [through_model._meta.get_field(f).column for f in ["observation", "resultqualifier"]]
151-
quoted_columns_sql = ", ".join([connection.ops.quote_name(c) for c in through_columns])
152+
through_columns = [
153+
through_model._meta.get_field(f).column
154+
for f in ["observation", "resultqualifier"]
155+
]
156+
quoted_columns_sql = ", ".join(
157+
[connection.ops.quote_name(c) for c in through_columns]
158+
)
152159

153-
with cursor.copy(f"COPY {through_table} ({quoted_columns_sql}) FROM STDIN") as copy:
160+
with cursor.copy(
161+
f"COPY {through_table} ({quoted_columns_sql}) FROM STDIN"
162+
) as copy:
154163
buffer = io.StringIO()
155164
for i in range(0, len(result_qualifiers), batch_size):
156-
batch = result_qualifiers[i: i + batch_size]
157-
lines = [f"{escape_pg_copy(obs_id)}\t{escape_pg_copy(rq_id)}" for obs_id, rq_id in batch]
165+
batch = result_qualifiers[i : i + batch_size]
166+
lines = [
167+
f"{escape_pg_copy(obs_id)}\t{escape_pg_copy(rq_id)}"
168+
for obs_id, rq_id in batch
169+
]
158170
buffer.write("\n".join(lines) + "\n")
159171
buffer.seek(0)
160172
copy.write(buffer.read())
@@ -171,7 +183,9 @@ class Observation(models.Model, PermissionChecker):
171183
result = models.FloatField()
172184
result_time = models.DateTimeField(null=True, blank=True)
173185
quality_code = models.CharField(max_length=255, null=True, blank=True)
174-
result_qualifiers = models.ManyToManyField(ResultQualifier, related_name="observations", blank=True)
186+
result_qualifiers = models.ManyToManyField(
187+
ResultQualifier, related_name="observations", blank=True
188+
)
175189

176190
objects = ObservationQuerySet.as_manager()
177191

@@ -249,7 +263,9 @@ def delete_contents(cls, filter_arg: models.Model, filter_suffix: Optional[str])
249263
f"observation__{filter_suffix}" if filter_suffix else "observation"
250264
)
251265

252-
cls.result_qualifiers.through.objects.filter(**{observation_relation_filter: filter_arg}).delete()
266+
cls.result_qualifiers.through.objects.filter(
267+
**{observation_relation_filter: filter_arg}
268+
).delete()
253269

254270
class Meta:
255271
constraints = [

sta/models/result_qualifier.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ class Meta:
7979
models.UniqueConstraint(
8080
fields=["code", "workspace_id"],
8181
name="unique_scoped_result_qualifier_code",
82-
nulls_distinct=False
82+
nulls_distinct=False,
8383
),
8484
]
8585

sta/models/thing.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,9 @@ def delete_contents(filter_arg: models.Model, filter_suffix: Optional[str]):
126126

127127
Location.objects.filter(**{thing_relation_filter: filter_arg}).delete()
128128
ThingTag.objects.filter(**{thing_relation_filter: filter_arg}).delete()
129-
ThingFileAttachment.objects.filter(**{thing_relation_filter: filter_arg}).delete()
129+
ThingFileAttachment.objects.filter(
130+
**{thing_relation_filter: filter_arg}
131+
).delete()
130132

131133

132134
class ThingTagQuerySet(models.QuerySet):
@@ -172,7 +174,9 @@ def visible(self, principal: Optional[Union["User", "APIKey"]]):
172174

173175

174176
class ThingTag(models.Model, PermissionChecker):
175-
thing = models.ForeignKey(Thing, related_name="thing_tags", on_delete=models.DO_NOTHING)
177+
thing = models.ForeignKey(
178+
Thing, related_name="thing_tags", on_delete=models.DO_NOTHING
179+
)
176180
key = models.CharField(max_length=255)
177181
value = models.CharField(max_length=255)
178182

@@ -187,7 +191,9 @@ def thing_file_attachment_storage_path(instance, filename):
187191

188192

189193
class ThingFileAttachment(models.Model, PermissionChecker):
190-
thing = models.ForeignKey(Thing, related_name="thing_file_attachments", on_delete=models.DO_NOTHING)
194+
thing = models.ForeignKey(
195+
Thing, related_name="thing_file_attachments", on_delete=models.DO_NOTHING
196+
)
191197
name = models.CharField(max_length=255)
192198
file_attachment = models.FileField(upload_to=thing_file_attachment_storage_path)
193199
file_attachment_type = models.CharField(max_length=200)

sta/schemas/__init__.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,13 @@
6262
ObservationBulkPostBody,
6363
ObservationBulkDeleteBody,
6464
)
65-
from .attachment import (TagGetResponse, TagPostBody, TagDeleteBody, FileAttachmentPostBody, FileAttachmentDeleteBody,
66-
FileAttachmentGetResponse)
65+
from .attachment import (
66+
TagGetResponse,
67+
TagPostBody,
68+
TagDeleteBody,
69+
FileAttachmentDeleteBody,
70+
FileAttachmentGetResponse,
71+
)
6772

6873

6974
from iam.schemas import WorkspaceSummaryResponse

sta/schemas/attachment.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,6 @@ class TagDeleteBody(BasePostBody):
2020
class FileAttachmentGetResponse(BaseGetResponse):
2121
name: str
2222
link: str
23-
24-
25-
class FileAttachmentPostBody(BasePostBody):
26-
name: str
2723
file_attachment_type: str
2824

2925

0 commit comments

Comments
 (0)