Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
beat
beat.web
Commits
95a2b05d
Commit
95a2b05d
authored
Sep 09, 2020
by
Samuel GAIST
Committed by
Flavio TARSETTI
Sep 14, 2020
Browse files
[reports][all] Pre-commit cleanup
parent
e893f0c4
Pipeline
#42746
passed with stage
in 15 minutes and 33 seconds
Changes
8
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
beat/web/reports/admin.py
View file @
95a2b05d
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
#!/usr/bin/env python
# encoding: utf-8
###############################################################################
...
...
@@ -30,86 +28,92 @@
# Flavio Tarsetti <flavio.tarsetti@idiap.ch>
# Wed May 20 15:46:11 CEST 2015
from
django.contrib
import
admi
n
import
simplejson
as
jso
n
from
django
import
forms
from
django.contrib
import
admin
from
..common.texts
import
Messages
from
..ui.forms
import
CodeMirrorJSONCharField
from
..ui.forms
import
CodeMirrorRSTCharField
from
.models
import
Report
from
..ui.forms
import
CodeMirrorRSTCharField
,
CodeMirrorJSONCharField
from
..ui.forms
import
NameField
import
simplejson
as
json
class
ReportModelForm
(
forms
.
ModelForm
):
description
=
CodeMirrorRSTCharField
(
label
=
'Description'
,
required
=
False
,
help_text
=
Messages
[
'description'
],
label
=
"Description"
,
required
=
False
,
help_text
=
Messages
[
"description"
],
)
content
=
CodeMirrorJSONCharField
(
label
=
'Content'
,
help_text
=
Messages
[
'json'
],
)
content
=
CodeMirrorJSONCharField
(
label
=
"Content"
,
help_text
=
Messages
[
"json"
],)
def
clean_content
(
self
):
"""Cleans-up the content data, make sure it is really new"""
try
:
data
=
json
.
loads
(
self
.
cleaned_data
[
'
content
'
])
data
=
json
.
loads
(
self
.
cleaned_data
[
"
content
"
])
return
json
.
dumps
(
data
,
indent
=
4
)
except
Exception
as
e
:
raise
forms
.
ValidationError
(
str
(
e
))
class
ReportAdmin
(
admin
.
ModelAdmin
):
form
=
ReportModelForm
readonly_fields
=
(
'
referenced_plotters
'
,
'
referenced_plotterparameters
'
)
readonly_fields
=
(
"
referenced_plotters
"
,
"
referenced_plotterparameters
"
)
filter_horizontal
=
[
'
experiments
'
,
'
referenced_plotters
'
,
'
referenced_plotterparameters
'
"
experiments
"
,
"
referenced_plotters
"
,
"
referenced_plotterparameters
"
,
]
fieldsets
=
(
(
None
,
dict
(
fields
=
(
'status'
,
'name'
,
'number'
,
'author'
,),
),
),
(
'Dates'
,
dict
(
classes
=
(
'collapse'
,),
fields
=
(
'creation_date'
,
'expiration_date'
,
'publication_date'
,),
),
),
(
'Documentation'
,
dict
(
classes
=
(
'collapse'
,),
fields
=
(
'short_description'
,
'description'
,),
),
),
(
None
,
dict
(
fields
=
(
'analyzer'
,
'experiments'
,
'referenced_plotters'
,
'referenced_plotterparameters'
,
'content'
,),
),
),
(
None
,
dict
(
fields
=
(
"status"
,
"name"
,
"number"
,
"author"
,),),),
(
"Dates"
,
dict
(
classes
=
(
"collapse"
,),
fields
=
(
"creation_date"
,
"expiration_date"
,
"publication_date"
,),
),
),
(
"Documentation"
,
dict
(
classes
=
(
"collapse"
,),
fields
=
(
"short_description"
,
"description"
,),),
),
(
None
,
dict
(
fields
=
(
"analyzer"
,
"experiments"
,
"referenced_plotters"
,
"referenced_plotterparameters"
,
"content"
,
),
),
),
)
list_display
=
(
'id'
,
'name'
,
'number'
,
'author'
,
'creation_date'
,
'expiration_date'
,
'publication_date'
)
search_fields
=
[
'author__username'
,
'name'
,
'short_description'
,
'description'
,
'number'
,
list_display
=
(
"id"
,
"name"
,
"number"
,
"author"
,
"creation_date"
,
"expiration_date"
,
"publication_date"
,
)
search_fields
=
[
"author__username"
,
"name"
,
"short_description"
,
"description"
,
"number"
,
]
list_display_links
=
(
'id'
,
'name'
)
list_display_links
=
(
"id"
,
"name"
)
list_filter
=
(
"author"
,
"name"
)
list_filter
=
(
'author'
,
'name'
)
admin
.
site
.
register
(
Report
,
ReportAdmin
)
beat/web/reports/api.py
View file @
95a2b05d
...
...
@@ -26,44 +26,38 @@
###############################################################################
import
json
from
datetime
import
datetime
,
timedelta
from
datetime
import
datetime
from
datetime
import
timedelta
from
django.conf
import
settings
from
django.contrib.auth.models
import
User
from
django.shortcuts
import
get_object_or_404
from
django.db.models
import
Q
from
django.shortcuts
import
get_object_or_404
from
django.urls
import
reverse
from
rest_framework
import
generics
from
rest_framework
import
views
from
rest_framework
import
permissions
from
rest_framework.response
import
Response
from
rest_framework
import
status
from
rest_framework
import
views
from
rest_framework.response
import
Response
from
..common.models
import
Shareable
from
..common.exceptions
import
ShareError
from
..common.mixins
import
CommonContextMixin
from
..common.responses
import
BadRequestResponse
,
ForbiddenResponse
from
..common.models
import
Shareable
from
..common.responses
import
BadRequestResponse
from
..common.responses
import
ForbiddenResponse
from
..common.utils
import
ensure_html
from
..experiments.serializers
import
ExperimentResultsSerializer
from
.serializers
import
SimpleReportSerializer
from
.models
import
Report
from
.permissions
import
IsAccessibleOutside
from
.permissions
import
IsAuthor
from
.permissions
import
IsAuthorOrPublished
from
.permissions
import
IsEditable
from
.permissions
import
IsLocked
from
.serializers
import
FullReportSerializer
from
.serializers
import
ReportCreationFailedException
from
.serializers
import
ReportCreationSerializer
from
.serializers
import
ReportUpdateSerializer
from
.serializers
import
ReportCreationFailedException
from
.models
import
Report
from
.permissions
import
(
IsAuthor
,
IsAuthorOrPublished
,
IsAccessibleOutside
,
IsEditable
,
IsLocked
,
)
from
.serializers
import
SimpleReportSerializer
# ----------------------------------------------------------
...
...
beat/web/reports/models.py
View file @
95a2b05d
...
...
@@ -25,55 +25,60 @@
# #
###############################################################################
from
django.db
import
models
import
random
from
datetime
import
datetime
import
simplejson
as
json
from
django.conf
import
settings
from
django.contrib.auth.models
import
User
from
django.core
import
exceptions
as
django_exceptions
from
django.db
import
models
from
django.urls
import
reverse
from
django.utils.encoding
import
force_bytes
,
force_text
from
django.conf
import
settings
from
..common.utils
import
validate_restructuredtext
from
..ui.templatetags.markup
import
restructuredtext
from
django.utils.encoding
import
force_bytes
from
django.utils.encoding
import
force_text
from
docutils.core
import
publish_parts
from
..algorithms.models
import
Algorithm
from
..common.texts
import
Messages
from
..experiments.models
import
Experiment
from
..plotters.models
import
Plotter
from
..plotters.models
import
PlotterParameter
from
..common.texts
import
Messages
import
random
from
datetime
import
datetime
import
simplejson
as
json
#----------------------------------------------------------
# ----------------------------------------------------------
class
ReportManager
(
models
.
Manager
):
def
create_object
(
self
,
author
,
name
,
short_description
=
''
,
description
=
''
,
content
=
{},
experiments
=
[]):
def
create_object
(
self
,
author
,
name
,
short_description
=
""
,
description
=
""
,
content
=
{},
experiments
=
[],
):
# Creation of the report
report
=
Report
()
report
.
name
=
name
report
.
author
=
author
report
=
Report
()
report
.
name
=
name
report
.
author
=
author
report
.
short_description
=
short_description
report
.
description
=
description
report
.
description
=
description
if
isinstance
(
content
,
dict
):
report
.
content
=
json
.
dumps
(
content
,
indent
=
4
)
report
.
content
=
json
.
dumps
(
content
,
indent
=
4
)
else
:
report
.
content
=
content
report
.
creation_date
=
datetime
.
now
()
report
.
last_edited_date
=
datetime
.
now
()
report
.
publication_date
=
None
report
.
expiration_date
=
None
report
.
status
=
self
.
model
.
EDITABLE
report
.
content
=
content
report
.
creation_date
=
datetime
.
now
()
report
.
last_edited_date
=
datetime
.
now
()
report
.
publication_date
=
None
report
.
expiration_date
=
None
report
.
status
=
self
.
model
.
EDITABLE
report
.
save
()
# Add the experiments
result
=
report
.
add_experiments
(
experiments
)
if
not
(
result
[
'
success
'
]):
if
not
(
result
[
"
success
"
]):
report
.
delete
()
report
=
None
...
...
@@ -88,116 +93,99 @@ class ReportManager(models.Manager):
def
published
(
self
):
return
self
.
filter
(
status
=
Report
.
PUBLISHED
)
#----------------------------------------------------------
# ----------------------------------------------------------
class
Report
(
models
.
Model
):
#_____ Constants __________
#
_____ Constants __________
EDITABLE
=
'E'
LOCKED
=
'L'
PUBLISHED
=
'P'
EDITABLE
=
"E"
LOCKED
=
"L"
PUBLISHED
=
"P"
REPORT_STATUS
=
(
(
EDITABLE
,
'
Editable
'
),
(
LOCKED
,
'
Locked
'
),
(
PUBLISHED
,
'
Published
'
),
(
EDITABLE
,
"
Editable
"
),
(
LOCKED
,
"
Locked
"
),
(
PUBLISHED
,
"
Published
"
),
)
# _____ Fields __________
#_____ Fields __________
status
=
models
.
CharField
(
max_length
=
1
,
choices
=
REPORT_STATUS
,
default
=
EDITABLE
)
name
=
models
.
CharField
(
max_length
=
200
,
help_text
=
Messages
[
'name'
],
blank
=
False
)
number
=
models
.
IntegerField
(
blank
=
True
)
author
=
models
.
ForeignKey
(
User
,
related_name
=
'%(class)ss'
,
on_delete
=
models
.
CASCADE
)
experiments
=
models
.
ManyToManyField
(
Experiment
,
related_name
=
'reports'
,
blank
=
True
)
creation_date
=
models
.
DateTimeField
()
last_edited_date
=
models
.
DateTimeField
(
null
=
True
)
expiration_date
=
models
.
DateTimeField
(
null
=
True
,
blank
=
True
)
publication_date
=
models
.
DateTimeField
(
null
=
True
,
blank
=
True
)
short_description
=
models
.
CharField
(
max_length
=
100
,
default
=
''
,
blank
=
True
,
help_text
=
Messages
[
'short_description'
])
description
=
models
.
TextField
(
default
=
''
,
blank
=
True
)
content
=
models
.
TextField
(
default
=
'{}'
,
blank
=
True
)
analyzer
=
models
.
ForeignKey
(
Algorithm
,
related_name
=
'reports'
,
null
=
True
,
blank
=
True
,
on_delete
=
models
.
CASCADE
)
status
=
models
.
CharField
(
max_length
=
1
,
choices
=
REPORT_STATUS
,
default
=
EDITABLE
)
name
=
models
.
CharField
(
max_length
=
200
,
help_text
=
Messages
[
"name"
],
blank
=
False
)
number
=
models
.
IntegerField
(
blank
=
True
)
author
=
models
.
ForeignKey
(
User
,
related_name
=
"%(class)ss"
,
on_delete
=
models
.
CASCADE
)
experiments
=
models
.
ManyToManyField
(
Experiment
,
related_name
=
"reports"
,
blank
=
True
)
creation_date
=
models
.
DateTimeField
()
last_edited_date
=
models
.
DateTimeField
(
null
=
True
)
expiration_date
=
models
.
DateTimeField
(
null
=
True
,
blank
=
True
)
publication_date
=
models
.
DateTimeField
(
null
=
True
,
blank
=
True
)
short_description
=
models
.
CharField
(
max_length
=
100
,
default
=
""
,
blank
=
True
,
help_text
=
Messages
[
"short_description"
]
)
description
=
models
.
TextField
(
default
=
""
,
blank
=
True
)
content
=
models
.
TextField
(
default
=
"{}"
,
blank
=
True
)
analyzer
=
models
.
ForeignKey
(
Algorithm
,
related_name
=
"reports"
,
null
=
True
,
blank
=
True
,
on_delete
=
models
.
CASCADE
,
)
# read-only parameters that are updated at every save(), if required
referenced_plotters
=
models
.
ManyToManyField
(
Plotter
,
related_name
=
'reports'
,
blank
=
True
)
referenced_plotterparameters
=
models
.
ManyToManyField
(
PlotterParameter
,
related_name
=
'reports'
,
blank
=
True
)
referenced_plotters
=
models
.
ManyToManyField
(
Plotter
,
related_name
=
"reports"
,
blank
=
True
)
referenced_plotterparameters
=
models
.
ManyToManyField
(
PlotterParameter
,
related_name
=
"reports"
,
blank
=
True
)
objects
=
ReportManager
()
def
__str__
(
self
):
return
"Report %s (#%d)"
%
(
self
.
fullname
(),
self
.
number
)
def
fullname
(
self
):
return
'%s/%s'
%
(
self
.
author
.
username
,
self
.
name
)
return
"%s/%s"
%
(
self
.
author
.
username
,
self
.
name
)
def
get_absolute_url
(
self
):
return
reverse
(
'reports:view'
,
args
=
(
self
.
number
,
),
)
return
reverse
(
"reports:view"
,
args
=
(
self
.
number
,),)
def
get_author_absolute_url
(
self
):
return
reverse
(
'reports:author-view'
,
args
=
(
self
.
author
.
username
,
self
.
name
),
)
return
reverse
(
"reports:author-view"
,
args
=
(
self
.
author
.
username
,
self
.
name
),)
def
get_api_update_url
(
self
):
return
reverse
(
'api_reports:object'
,
args
=
(
self
.
author
.
username
,
self
.
name
),
)
return
reverse
(
"api_reports:object"
,
args
=
(
self
.
author
.
username
,
self
.
name
),)
def
get_api_add_url
(
self
):
return
reverse
(
'api_reports:add_experiments'
,
args
=
(
self
.
author
.
username
,
self
.
name
),
"api_reports:add_experiments"
,
args
=
(
self
.
author
.
username
,
self
.
name
),
)
def
get_api_remove_url
(
self
):
return
reverse
(
'api_reports:remove_experiments'
,
args
=
(
self
.
author
.
username
,
self
.
name
),
"api_reports:remove_experiments"
,
args
=
(
self
.
author
.
username
,
self
.
name
),
)
def
save
(
self
,
*
args
,
**
kwargs
):
if
self
.
number
is
None
:
# Generate a unique report number
used_numbers
=
map
(
lambda
x
:
x
.
number
,
Report
.
objects
.
al
l
()
)
used_numbers
=
Report
.
objects
.
v
al
ues_list
(
"number"
,
flat
=
True
)
number
=
0
while
(
number
==
0
)
or
number
in
used_numbers
:
number
=
random
.
randint
(
100000
,
2
**
31
)
number
=
random
.
randint
(
100000
,
2
**
31
)
# nosec
self
.
number
=
number
report_content
=
json
.
loads
(
self
.
content
)
report_content_charts
=
dict
(
filter
(
lambda
item
:
item
[
0
].
startswith
(
"chart"
),
report_content
.
items
()))
report_content_charts
=
dict
(
filter
(
lambda
item
:
item
[
0
].
startswith
(
"chart"
),
report_content
.
items
())
)
self
.
last_edited_date
=
datetime
.
now
()
...
...
@@ -206,38 +194,46 @@ class Report(models.Model):
self
.
referenced_plotters
.
clear
()
self
.
referenced_plotterparameters
.
clear
()
for
key
,
value
in
report_content_charts
.
items
():
plotter_parts
=
value
[
'data'
][
'plotter'
].
split
(
"/"
)
plotterparameters_parts
=
value
[
'selected_template'
].
split
(
"/"
)
plotter
=
Plotter
.
objects
.
get
(
author__username
=
plotter_parts
[
0
],
name
=
plotter_parts
[
1
],
version
=
plotter_parts
[
2
])
plotterparameter
=
PlotterParameter
.
objects
.
get
(
author__username
=
plotterparameters_parts
[
0
],
name
=
plotterparameters_parts
[
1
],
version
=
plotterparameters_parts
[
2
])
plotter_parts
=
value
[
"data"
][
"plotter"
].
split
(
"/"
)
plotterparameters_parts
=
value
[
"selected_template"
].
split
(
"/"
)
plotter
=
Plotter
.
objects
.
get
(
author__username
=
plotter_parts
[
0
],
name
=
plotter_parts
[
1
],
version
=
plotter_parts
[
2
],
)
plotterparameter
=
PlotterParameter
.
objects
.
get
(
author__username
=
plotterparameters_parts
[
0
],
name
=
plotterparameters_parts
[
1
],
version
=
plotterparameters_parts
[
2
],
)
self
.
referenced_plotters
.
add
(
plotter
)
self
.
referenced_plotterparameters
.
add
(
plotterparameter
)
def
add_experiments
(
self
,
experiment_fullname_list
):
# Check that the report is modifiable
if
self
.
status
!=
Report
.
EDITABLE
:
return
{
'
success
'
:
False
,
'
error
'
:
"Report not modifiable"
,
"
success
"
:
False
,
"
error
"
:
"Report not modifiable"
,
}
# Process the list of experiments
accessible_experiments
=
[]
inaccessible_experiments
=
[]
experiments
,
unknown_experiments
=
self
.
_get_experiments_from_fullname_list
(
experiment_fullname_list
)
experiments
,
unknown_experiments
=
self
.
_get_experiments_from_fullname_list
(
experiment_fullname_list
)
for
experiment
in
experiments
:
# Check experiments accessibility
(
is_accessible
,
accessibility
)
=
experiment
.
accessibility_for
(
self
.
author
)
if
not
(
is_accessible
)
or
(
experiment
.
status
!=
Experiment
.
DONE
):
if
not
(
is_accessible
)
or
(
experiment
.
status
!=
Experiment
.
DONE
):
inaccessible_experiments
.
append
(
experiment
.
fullname
())
continue
accessible_experiments
.
append
(
experiment
)
# Add the experiments to the report
incompatible_experiments
=
[]
for
experiment
in
accessible_experiments
:
...
...
@@ -247,20 +243,21 @@ class Report(models.Model):
incompatible_experiments
.
append
(
experiment
.
fullname
())
return
{
'
success
'
:
True
,
'
unknown_experiments
'
:
unknown_experiments
,
'
inaccessible_experiments
'
:
inaccessible_experiments
,
'
incompatible_experiments
'
:
incompatible_experiments
,
"
success
"
:
True
,
"
unknown_experiments
"
:
unknown_experiments
,
"
inaccessible_experiments
"
:
inaccessible_experiments
,
"
incompatible_experiments
"
:
incompatible_experiments
,
}
def
remove_experiments
(
self
,
experiment_fullname_list
):
# Check that the report is modifiable
if
self
.
status
!=
Report
.
EDITABLE
:
return
experiments
,
unknown_experiments
=
self
.
_get_experiments_from_fullname_list
(
experiment_fullname_list
)
experiments
,
unknown_experiments
=
self
.
_get_experiments_from_fullname_list
(
experiment_fullname_list
)
for
experiment
in
experiments
:
self
.
experiments
.
remove
(
experiment
)
...
...
@@ -269,23 +266,26 @@ class Report(models.Model):
self
.
analyzer
=
None
self
.
save
()
def
_get_experiments_from_fullname_list
(
self
,
experiment_fullname_list
):
experiments
=
[]
unknown_experiments
=
[]
for
experiment_name
in
experiment_fullname_list
:
parts
=
experiment_name
.
split
(
'/'
)
parts
=
experiment_name
.
split
(
"/"
)
if
len
(
parts
)
!=
5
:
raise
ValidationError
({
'experiment'
:
'Invalid experiment full name'
})
raise
django_exceptions
.
ValidationError
(
{
"experiment"
:
"Invalid experiment full name"
}
)
try
:
experiment
=
Experiment
.
objects
.
get
(
author__username
=
parts
[
0
],
toolchain__author__username
=
parts
[
1
],
toolchain__name
=
parts
[
2
],
toolchain__version
=
int
(
parts
[
3
]),
name
=
parts
[
4
])
experiment
=
Experiment
.
objects
.
get
(
author__username
=
parts
[
0
],
toolchain__author__username
=
parts
[
1
],
toolchain__name
=
parts
[
2
],
toolchain__version
=
int
(
parts
[
3
]),
name
=
parts
[
4
],
)
except
Experiment
.
DoesNotExist
:
unknown_experiments
.
append
(
experiment_name
)
else
:
...
...
@@ -293,7 +293,6 @@ class Report(models.Model):
return
experiments
,
unknown_experiments
def
_get_experiments_and_alias
(
self
,
alias_filter
):
experiments_list
=
[]
...
...
@@ -306,38 +305,40 @@ class Report(models.Model):
for
experiment
in
self
.
experiments
.
iterator
():
if
experiment
.
fullname
()
not
in
report_content
[
"alias_experiments"
]:
report_content
[
"alias_experiments"
][
experiment
.
fullname
()]
=
experiment
.
name
report_content
[
"alias_experiments"
][
experiment
.
fullname
()
]
=
experiment
.
name
try
:
index
=
alias_filter
.
index
(
report_content
[
"alias_experiments"
][
experiment
.
fullname
()])
alias_filter
.
index
(
report_content
[
"alias_experiments"
][
experiment
.
fullname
()]
)
experiments_list
.
append
(
experiment
.
fullname
())
except
:
except
Exception
:
# nosec
pass
alias_list
=
map
(
lambda
x
:
report_content
[
"alias_experiments"
][
x
],
experiments_list
)
alias_list
=
map
(
lambda
x
:
report_content
[
"alias_experiments"
][
x
],
experiments_list