Skip to content

Commit 25022e1

Browse files
committed
style: apply ruff formatting
1 parent 427005a commit 25022e1

14 files changed

Lines changed: 424 additions & 105 deletions

tracker/admin.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,14 +130,21 @@ class ObservationSessionAdmin(admin.ModelAdmin):
130130
inlines = [SessionVideoInline, VariableValueInline]
131131

132132

133-
134-
135133
@admin.register(ObservationSegment)
136134
class ObservationSegmentAdmin(admin.ModelAdmin):
137-
list_display = ('session', 'title', 'start_seconds', 'end_seconds', 'status', 'assignee', 'reviewer')
135+
list_display = (
136+
'session',
137+
'title',
138+
'start_seconds',
139+
'end_seconds',
140+
'status',
141+
'assignee',
142+
'reviewer',
143+
)
138144
list_filter = ('session__project', 'status')
139145
search_fields = ('session__title', 'title', 'notes', 'assignee__username', 'reviewer__username')
140146

147+
141148
@admin.register(ObservationEvent)
142149
class ObservationEventAdmin(admin.ModelAdmin):
143150
list_display = (

tracker/compatibility.py

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,6 @@ def _resolve_annotation_items(payload: dict[str, Any]) -> list[dict[str, Any]]:
7474
return []
7575

7676

77-
78-
7977
def _resolve_segment_items(payload: dict[str, Any]) -> list[dict[str, Any]]:
8078
if payload.get('schema', '').startswith('pybehaviorlog-'):
8179
return [item for item in payload.get('segments', []) if isinstance(item, dict)]
@@ -103,13 +101,19 @@ def normalize_session_payload(payload: dict[str, Any]) -> dict[str, Any]:
103101
event_kind = str(item.get('event_kind') or item.get('type') or 'point').lower()
104102
events.append(
105103
{
106-
'time': _normalize_time(item.get('time') or item.get('timestamp_seconds') or item.get('start')),
104+
'time': _normalize_time(
105+
item.get('time') or item.get('timestamp_seconds') or item.get('start')
106+
),
107107
'behavior': str(behavior),
108108
'event_kind': event_kind,
109109
'modifiers': _string_list(item.get('modifiers')),
110110
'subjects': _string_list(item.get('subjects') or item.get('subject')),
111-
'comment': str(item.get('comment') or item.get('comment_start') or item.get('image_path') or ''),
112-
'frame_index': int(item.get('frame_index') or item.get('frame') or 0) if str(item.get('frame_index') or item.get('frame') or '').strip() else None,
111+
'comment': str(
112+
item.get('comment') or item.get('comment_start') or item.get('image_path') or ''
113+
),
114+
'frame_index': int(item.get('frame_index') or item.get('frame') or 0)
115+
if str(item.get('frame_index') or item.get('frame') or '').strip()
116+
else None,
113117
}
114118
)
115119
events.sort(key=lambda item: (item['time'], item['behavior'], item['event_kind']))
@@ -124,12 +128,14 @@ def normalize_session_payload(payload: dict[str, Any]) -> dict[str, Any]:
124128
annotations.sort(key=lambda item: (item['time'], item['text']))
125129
segments = []
126130
for item in _resolve_segment_items(payload):
127-
segments.append({
128-
'title': str(item.get('title') or ''),
129-
'start': _normalize_time(item.get('start_seconds') or item.get('start')),
130-
'end': _normalize_time(item.get('end_seconds') or item.get('end')),
131-
'status': str(item.get('status') or ''),
132-
})
131+
segments.append(
132+
{
133+
'title': str(item.get('title') or ''),
134+
'start': _normalize_time(item.get('start_seconds') or item.get('start')),
135+
'end': _normalize_time(item.get('end_seconds') or item.get('end')),
136+
'status': str(item.get('status') or ''),
137+
}
138+
)
133139
segments.sort(key=lambda item: (item['start'], item['end'], item['title']))
134140
variables = payload.get('variables') or payload.get('independent_variables') or {}
135141
if not isinstance(variables, dict):
@@ -139,7 +145,9 @@ def normalize_session_payload(payload: dict[str, Any]) -> dict[str, Any]:
139145
'events': events,
140146
'annotations': annotations,
141147
'variables': {str(key): str(value) for key, value in sorted(variables.items())},
142-
'media_paths': sorted(_string_list(payload.get('media_paths') or payload.get('image_paths'))),
148+
'media_paths': sorted(
149+
_string_list(payload.get('media_paths') or payload.get('image_paths'))
150+
),
143151
'segments': segments,
144152
}
145153

@@ -169,6 +177,7 @@ def compare_session_payloads(expected: dict[str, Any], actual: dict[str, Any]) -
169177

170178
def normalize_project_payload(payload: dict[str, Any]) -> dict[str, Any]:
171179
"""Normalize project-like payloads for BORIS/PyBehaviorLog round-trip comparisons."""
180+
172181
def _item_names(value: Any, *, key: str = 'name', fallback: str = 'label') -> list[str]:
173182
results = []
174183
if isinstance(value, dict):
@@ -200,15 +209,21 @@ def _item_names(value: Any, *, key: str = 'name', fallback: str = 'label') -> li
200209
if isinstance(observations, list):
201210
for observation in observations:
202211
if isinstance(observation, dict):
203-
session_titles.append(str(observation.get('title') or observation.get('description') or ''))
212+
session_titles.append(
213+
str(observation.get('title') or observation.get('description') or '')
214+
)
204215
return {
205216
'schema_family': str(payload.get('schema') or 'unknown'),
206217
'categories': _item_names(payload.get('categories')),
207218
'behaviors': _item_names(payload.get('behaviors')),
208219
'modifiers': _item_names(payload.get('modifiers')),
209220
'subject_groups': _item_names(payload.get('subject_groups')),
210221
'subjects': _item_names(payload.get('subjects')),
211-
'variables': _item_names(payload.get('variables') or payload.get('independent_variables'), key='label', fallback='name'),
222+
'variables': _item_names(
223+
payload.get('variables') or payload.get('independent_variables'),
224+
key='label',
225+
fallback='name',
226+
),
212227
'templates': _item_names(payload.get('observation_templates')),
213228
'sessions': sorted(item for item in session_titles if item),
214229
}
@@ -219,7 +234,16 @@ def compare_project_payloads(expected: dict[str, Any], actual: dict[str, Any]) -
219234
actual_normalized = normalize_project_payload(actual)
220235
mismatches = [
221236
key
222-
for key in ('categories', 'behaviors', 'modifiers', 'subject_groups', 'subjects', 'variables', 'templates', 'sessions')
237+
for key in (
238+
'categories',
239+
'behaviors',
240+
'modifiers',
241+
'subject_groups',
242+
'subjects',
243+
'variables',
244+
'templates',
245+
'sessions',
246+
)
223247
if expected_normalized[key] != actual_normalized[key]
224248
]
225249
return {
@@ -230,7 +254,9 @@ def compare_project_payloads(expected: dict[str, Any], actual: dict[str, Any]) -
230254
}
231255

232256

233-
def build_roundtrip_report(expected: dict[str, Any], actual: dict[str, Any], family: str) -> dict[str, Any]:
257+
def build_roundtrip_report(
258+
expected: dict[str, Any], actual: dict[str, Any], family: str
259+
) -> dict[str, Any]:
234260
"""Build a machine-readable round-trip report for CI and fixture certification."""
235261
comparator = compare_project_payloads if family == 'project' else compare_session_payloads
236262
comparison = comparator(expected, actual)

tracker/forms.py

Lines changed: 71 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,9 @@ class Meta:
127127

128128

129129
class EthogramImportForm(forms.Form):
130-
131130
file = forms.FileField(
132131
label=_('File'),
133-
help_text=_(
134-
'JSON export from PyBehaviorLog 0.9.1 or BORIS-compatible JSON.'
135-
),
132+
help_text=_('JSON export from PyBehaviorLog 0.9.1 or BORIS-compatible JSON.'),
136133
)
137134
replace_existing = forms.BooleanField(
138135
required=False,
@@ -164,7 +161,12 @@ class ProjectBORISImportForm(forms.Form):
164161

165162

166163
class SessionImportForm(forms.Form):
167-
file = forms.FileField(label=_('File'), help_text=_('PyBehaviorLog 0.9.1 JSON, BORIS observation JSON, spreadsheet-like session tables, or CowLog plain-text coding results.'))
164+
file = forms.FileField(
165+
label=_('File'),
166+
help_text=_(
167+
'PyBehaviorLog 0.9.1 JSON, BORIS observation JSON, spreadsheet-like session tables, or CowLog plain-text coding results.'
168+
),
169+
)
168170
clear_existing = forms.BooleanField(
169171
required=False,
170172
label=_('Delete existing events and annotations before import'),
@@ -187,7 +189,12 @@ class Meta:
187189
'description': forms.TextInput(),
188190
'key_binding': forms.TextInput(attrs={'maxlength': 1}),
189191
}
190-
labels = {'name': _('Name'), 'description': _('Description'), 'key_binding': _('Key binding'), 'sort_order': _('Sort order')}
192+
labels = {
193+
'name': _('Name'),
194+
'description': _('Description'),
195+
'key_binding': _('Key binding'),
196+
'sort_order': _('Sort order'),
197+
}
191198

192199
def clean_key_binding(self):
193200
return self.cleaned_data['key_binding'].upper()
@@ -201,7 +208,12 @@ class Meta:
201208
'description': forms.TextInput(),
202209
'color': forms.TextInput(attrs={'type': 'color'}),
203210
}
204-
labels = {'name': _('Name'), 'description': _('Description'), 'color': _('Color'), 'sort_order': _('Sort order')}
211+
labels = {
212+
'name': _('Name'),
213+
'description': _('Description'),
214+
'color': _('Color'),
215+
'sort_order': _('Sort order'),
216+
}
205217

206218

207219
class SubjectForm(forms.ModelForm):
@@ -214,7 +226,14 @@ class Meta:
214226
'color': forms.TextInput(attrs={'type': 'color'}),
215227
'groups': forms.CheckboxSelectMultiple(),
216228
}
217-
labels = {'name': _('Name'), 'description': _('Description'), 'groups': _('Groups'), 'key_binding': _('Key binding'), 'color': _('Color'), 'sort_order': _('Sort order')}
229+
labels = {
230+
'name': _('Name'),
231+
'description': _('Description'),
232+
'groups': _('Groups'),
233+
'key_binding': _('Key binding'),
234+
'color': _('Color'),
235+
'sort_order': _('Sort order'),
236+
}
218237

219238
def __init__(self, *args, project=None, **kwargs):
220239
super().__init__(*args, **kwargs)
@@ -236,7 +255,14 @@ class Meta:
236255
'set_values': forms.Textarea(attrs={'rows': 3}),
237256
'default_value': forms.TextInput(),
238257
}
239-
labels = {'label': _('Label'), 'description': _('Description'), 'value_type': _('Value type'), 'set_values': _('Allowed values'), 'default_value': _('Default value'), 'sort_order': _('Sort order')}
258+
labels = {
259+
'label': _('Label'),
260+
'description': _('Description'),
261+
'value_type': _('Value type'),
262+
'set_values': _('Allowed values'),
263+
'default_value': _('Default value'),
264+
'sort_order': _('Sort order'),
265+
}
240266

241267

242268
class BehaviorForm(forms.ModelForm):
@@ -248,7 +274,15 @@ class Meta:
248274
'key_binding': forms.TextInput(attrs={'maxlength': 1}),
249275
'color': forms.TextInput(attrs={'type': 'color'}),
250276
}
251-
labels = {'category': _('Category'), 'name': _('Name'), 'description': _('Description'), 'key_binding': _('Key binding'), 'color': _('Color'), 'mode': _('Mode'), 'sort_order': _('Sort order')}
277+
labels = {
278+
'category': _('Category'),
279+
'name': _('Name'),
280+
'description': _('Description'),
281+
'key_binding': _('Key binding'),
282+
'color': _('Color'),
283+
'mode': _('Mode'),
284+
'sort_order': _('Sort order'),
285+
}
252286

253287
def __init__(self, *args, project=None, **kwargs):
254288
super().__init__(*args, **kwargs)
@@ -279,7 +313,15 @@ class Meta:
279313
'subjects': forms.CheckboxSelectMultiple(),
280314
'variable_definitions': forms.CheckboxSelectMultiple(),
281315
}
282-
labels = {'name': _('Name'), 'description': _('Description'), 'default_session_kind': _('Default session kind'), 'behaviors': _('Behaviors'), 'modifiers': _('Modifiers'), 'subjects': _('Subjects'), 'variable_definitions': _('Independent variables')}
316+
labels = {
317+
'name': _('Name'),
318+
'description': _('Description'),
319+
'default_session_kind': _('Default session kind'),
320+
'behaviors': _('Behaviors'),
321+
'modifiers': _('Modifiers'),
322+
'subjects': _('Subjects'),
323+
'variable_definitions': _('Independent variables'),
324+
}
283325

284326
def __init__(self, *args, project=None, **kwargs):
285327
super().__init__(*args, **kwargs)
@@ -308,11 +350,18 @@ def __init__(self, *args, **kwargs):
308350
self.fields['file'].required = False
309351

310352

311-
312353
class ObservationSegmentForm(forms.ModelForm):
313354
class Meta:
314355
model = ObservationSegment
315-
fields = ['title', 'start_seconds', 'end_seconds', 'status', 'assignee', 'reviewer', 'notes']
356+
fields = [
357+
'title',
358+
'start_seconds',
359+
'end_seconds',
360+
'status',
361+
'assignee',
362+
'reviewer',
363+
'notes',
364+
]
316365
widgets = {'notes': forms.Textarea(attrs={'rows': 3})}
317366
labels = {
318367
'title': _('Title'),
@@ -328,7 +377,9 @@ def __init__(self, *args, project=None, **kwargs):
328377
super().__init__(*args, **kwargs)
329378
queryset = User.objects.order_by('username')
330379
if project is not None:
331-
member_ids = list(project.memberships.values_list('user_id', flat=True)) + [project.owner_id]
380+
member_ids = list(project.memberships.values_list('user_id', flat=True)) + [
381+
project.owner_id
382+
]
332383
queryset = queryset.filter(pk__in=member_ids).distinct()
333384
self.fields['assignee'].queryset = queryset
334385
self.fields['reviewer'].queryset = queryset
@@ -338,7 +389,9 @@ def clean(self):
338389
start = cleaned.get('start_seconds')
339390
end = cleaned.get('end_seconds')
340391
if start is not None and end is not None and end < start:
341-
self.add_error('end_seconds', _('End time must be greater than or equal to start time.'))
392+
self.add_error(
393+
'end_seconds', _('End time must be greater than or equal to start time.')
394+
)
342395
return cleaned
343396

344397

@@ -438,9 +491,9 @@ def __init__(self, *args, project=None, **kwargs):
438491
definition.value_type == IndependentVariableDefinition.TYPE_SET
439492
and definition.set_values
440493
):
441-
help_text = (
442-
help_text + ' ' if help_text else ''
443-
) + _('Allowed values: %(values)s') % {'values': definition.set_values}
494+
help_text = (help_text + ' ' if help_text else '') + _(
495+
'Allowed values: %(values)s'
496+
) % {'values': definition.set_values}
444497
field.help_text = help_text
445498
self.fields[field_name] = field
446499
initial_value = definition.default_value

tracker/management/commands/export_project_bundle.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88

99
class Command(BaseCommand):
10-
help = "Export a PyBehaviorLog reproducibility bundle for a project."
10+
help = 'Export a PyBehaviorLog reproducibility bundle for a project.'
1111

1212
def add_arguments(self, parser):
1313
parser.add_argument('project_id', type=int)

tracker/management/commands/release_report.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77

88
class Command(BaseCommand):
9-
help = "Print machine-readable release metadata for PyBehaviorLog."
9+
help = 'Print machine-readable release metadata for PyBehaviorLog.'
1010

1111
def handle(self, *args, **options):
1212
self.stdout.write(json.dumps(build_release_metadata(), indent=2, ensure_ascii=False))

tracker/models.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,9 @@ class IndependentVariableDefinition(models.Model):
256256
label = models.CharField(max_length=120)
257257
description = models.CharField(max_length=255, blank=True)
258258
value_type = models.CharField(max_length=20, choices=TYPE_CHOICES, default=TYPE_TEXT)
259-
set_values = models.TextField(blank=True, help_text=_('Comma-separated values for list fields.'))
259+
set_values = models.TextField(
260+
blank=True, help_text=_('Comma-separated values for list fields.')
261+
)
260262
default_value = models.CharField(max_length=255, blank=True)
261263
sort_order = models.PositiveIntegerField(default=0)
262264

@@ -563,7 +565,6 @@ def duration_seconds(self) -> float:
563565
return round(float(self.end_seconds - self.start_seconds), 3)
564566

565567

566-
567568
class ObservationEvent(models.Model):
568569
KIND_POINT = 'point'
569570
KIND_START = 'start'

tracker/tests/test_compatibility.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ def test_session_import_view_accepts_cowlog_text(self):
7777
self.assertEqual(event.behavior.name, 'Eat')
7878
self.assertEqual(event.modifiers_display, 'Near')
7979

80-
8180
def test_load_session_import_payload_supports_state_intervals_from_tabular_rows(self):
8281
upload = SimpleUploadedFile(
8382
'boris_rows.csv',
@@ -181,15 +180,19 @@ def test_export_endpoints_for_compatibility_formats(self):
181180
event_kind=ObservationEvent.KIND_POINT,
182181
timestamp_seconds=Decimal('1.000'),
183182
)
184-
response = self.client.get(reverse('tracker:session_export_cowlog_txt', args=[self.session.pk]))
183+
response = self.client.get(
184+
reverse('tracker:session_export_cowlog_txt', args=[self.session.pk])
185+
)
185186
self.assertEqual(response.status_code, 200)
186187
self.assertIn('CowLog-compatible', response.content.decode('utf-8'))
187188
response = self.client.get(
188189
reverse('tracker:session_export_behavioral_sequences', args=[self.session.pk])
189190
)
190191
self.assertEqual(response.status_code, 200)
191192
self.assertIn('# observation id:', response.content.decode('utf-8'))
192-
response = self.client.get(reverse('tracker:session_export_textgrid', args=[self.session.pk]))
193+
response = self.client.get(
194+
reverse('tracker:session_export_textgrid', args=[self.session.pk])
195+
)
193196
self.assertEqual(response.status_code, 200)
194197
self.assertIn('TextGrid', response.content.decode('utf-8'))
195198
response = self.client.get(

0 commit comments

Comments
 (0)