Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
GraceDB Server
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Michael William Coughlin
GraceDB Server
Commits
6db1dbcb
Commit
6db1dbcb
authored
12 years ago
by
Branson Stephens
Browse files
Options
Downloads
Patches
Plain Diff
Initial commit for tags.
parent
e5512027
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
gracedb/api.py
+290
-2
290 additions, 2 deletions
gracedb/api.py
gracedb/models.py
+54
-1
54 additions, 1 deletion
gracedb/models.py
gracedb/urls_rest.py
+17
-0
17 additions, 0 deletions
gracedb/urls_rest.py
with
361 additions
and
3 deletions
gracedb/api.py
+
290
−
2
View file @
6db1dbcb
...
...
@@ -8,7 +8,7 @@ from django.conf import settings
import
json
from
gracedb.models
import
Event
,
Group
,
EventLog
,
Slot
from
gracedb.models
import
Event
,
Group
,
EventLog
,
Slot
,
Tag
from
gracedb.views
import
create_label
from
translator
import
handle_uploaded_data
...
...
@@ -115,6 +115,7 @@ def eventToDict(event, columns=None, request=None):
"
filemeta
"
:
reverse
(
"
filemeta
"
,
args
=
[
graceid
],
request
=
request
),
"
labels
"
:
reverse
(
"
labels
"
,
args
=
[
graceid
],
request
=
request
),
"
self
"
:
reverse
(
"
event-detail
"
,
args
=
[
graceid
],
request
=
request
),
"
tags
"
:
reverse
(
"
eventtag-list
"
,
args
=
[
graceid
],
request
=
request
),
}
# XXX Jam the slots in here? Could just have a list of slot names instead of
# all these links. But the links might be useful??
...
...
@@ -472,12 +473,16 @@ class EventLabel(APIView):
# Janky serialization
def
eventLogToDict
(
log
,
n
=
None
,
request
=
None
):
# XXX Messy. n should not be here but in the model.
taglist_uri
=
None
if
(
n
is
None
)
and
request
:
uri
=
request
.
build_absolute_uri
()
elif
n
is
not
None
and
request
:
uri
=
reverse
(
"
eventlog-detail
"
,
args
=
[
log
.
event
.
graceid
(),
n
],
request
=
request
)
taglist_uri
=
reverse
(
"
eventlogtag-list
"
,
args
=
[
log
.
event
.
graceid
(),
n
],
request
=
request
)
else
:
uri
=
None
return
{
...
...
@@ -485,6 +490,7 @@ def eventLogToDict(log, n=None, request=None):
"
created
"
:
log
.
created
,
"
issuer
"
:
log
.
issuer
.
name
,
"
self
"
:
uri
,
"
tags
"
:
taglist_uri
,
}
class
EventLogList
(
APIView
):
...
...
@@ -547,7 +553,254 @@ class EventLogDetail(APIView):
return
Response
(
"
Log Entry Not Found
"
,
status
=
status
.
HTTP_404_NOT_FOUND
)
rv
=
event
.
eventlog_set
.
order_by
(
"
created
"
).
all
()[
int
(
n
)]
return
Response
(
eventLogToDict
(
rv
,
request
=
request
))
# XXX I (Branson) put the n argument here. Why not?
# We might as well since we have it, right?
return
Response
(
eventLogToDict
(
rv
,
n
,
request
=
request
))
#==================================================================
# Tags
def
tagToDict
(
tag
,
columns
=
None
,
request
=
None
,
event
=
None
,
n
=
None
):
"""
Convert a tag to a dictionary.
Output depends on the level of specificity.
"""
rv
=
{}
rv
[
'
name
'
]
=
tag
.
name
rv
[
'
displayName
'
]
=
tag
.
displayName
if
event
:
if
n
:
# We want a link to the self only. End of the line.
rv
[
'
links
'
]
=
{
"
self
"
:
reverse
(
"
eventlogtag-detail
"
,
args
=
[
event
.
graceid
(),
n
,
tag
.
name
],
request
=
request
)
}
else
:
# Links to all log messages of the event with this tag.
rv
[
'
links
'
]
=
{
"
logs
"
:
[
reverse
(
"
eventlog-detail
"
,
args
=
[
event
.
graceid
(),
log
.
getN
()],
request
=
request
)
for
log
in
event
.
getLogsForTag
(
tag
.
name
)],
"
self
"
:
reverse
(
"
eventtag-detail
"
,
args
=
[
event
.
graceid
(),
tag
.
name
],
request
=
request
)
}
else
:
# Links to all events that have this tag.
rv
[
'
links
'
]
=
{
"
events
"
:
[
reverse
(
"
event-detail
"
,
args
=
[
event
.
graceid
()],
request
=
request
)
for
event
in
tag
.
getEvents
()],
"
self
"
:
reverse
(
"
tag-detail
"
,
args
=
[
tag
.
name
],
request
=
request
)
}
return
rv
class
TagList
(
APIView
):
"""
Tag List Resource
"""
authentication_classes
=
(
LigoAuthentication
,)
permission_classes
=
(
IsAuthenticated
,)
def
get
(
self
,
request
):
# Return a list of links to all tag objects.
rv
=
{
'
tags
'
:
[
reverse
(
"
tag-detail
"
,
args
=
[
tag
.
name
],
request
=
request
)
for
tag
in
Tag
.
objects
.
all
()
]
}
return
Response
(
rv
)
class
TagDetail
(
APIView
):
"""
Tag Detail Resource
"""
authentication_classes
=
(
LigoAuthentication
,)
permission_classes
=
(
IsAuthenticated
,)
def
get
(
self
,
request
,
tagname
):
try
:
tag
=
Tag
.
objects
.
filter
(
name
=
tagname
)[
0
]
except
Tag
.
DoesNotExist
:
return
Response
(
"
Tag not found.
"
,
status
=
status
.
HTTP_404_NOT_FOUND
)
return
Response
(
tagToDict
(
tag
,
request
=
request
))
class
EventTagList
(
APIView
):
"""
Event Tag List Resource
"""
authentication_classes
=
(
LigoAuthentication
,)
permission_classes
=
(
IsAuthenticated
,)
def
get
(
self
,
request
,
graceid
):
# Return a list of links to all tags for this event.
try
:
event
=
Event
.
getByGraceid
(
graceid
)
except
Event
.
DoesNotExist
:
# XXX Real error message.
return
Response
(
"
Event does not exist.
"
,
status
=
status
.
HTTP_404_NOT_FOUND
)
rv
=
{
'
tags
'
:
[
reverse
(
"
eventtag-detail
"
,
args
=
[
graceid
,
tag
.
name
],
request
=
request
)
for
tag
in
event
.
getAvailableTags
()]
}
return
Response
(
rv
)
class
EventTagDetail
(
APIView
):
"""
Event Tag List Resource
"""
authentication_classes
=
(
LigoAuthentication
,)
permission_classes
=
(
IsAuthenticated
,)
def
get
(
self
,
request
,
graceid
,
tagname
):
try
:
event
=
Event
.
getByGraceid
(
graceid
)
except
Event
.
DoesNotExist
:
# XXX Real error message.
return
Response
(
"
Event does not exist.
"
,
status
=
status
.
HTTP_404_NOT_FOUND
)
try
:
tag
=
Tag
.
objects
.
filter
(
name
=
tagname
)[
0
]
rv
=
tagToDict
(
tag
,
event
=
event
,
request
=
request
)
return
Response
(
rv
)
except
Tag
.
DoesNotExist
:
return
Response
(
"
No such tag for event.
"
,
status
=
status
.
HTTP_404_NOT_FOUND
)
class
EventLogTagList
(
APIView
):
"""
Event Log Tag List Resource
"""
authentication_classes
=
(
LigoAuthentication
,)
permission_classes
=
(
IsAuthenticated
,)
def
get
(
self
,
request
,
graceid
,
n
):
# Return a list of links to tags associated with a given log message
try
:
event
=
Event
.
getByGraceid
(
graceid
)
eventlog
=
event
.
eventlog_set
.
order_by
(
"
created
"
).
all
()[
int
(
n
)]
except
Event
.
DoesNotExist
:
# XXX Real error message.
return
Response
(
"
Event does not exist.
"
,
status
=
status
.
HTTP_404_NOT_FOUND
)
except
:
# XXX Real error message.
return
Response
(
"
Log does not exist.
"
,
status
=
status
.
HTTP_404_NOT_FOUND
)
rv
=
{
'
tags
'
:
[
reverse
(
"
eventlogtag-detail
"
,
args
=
[
graceid
,
n
,
tag
.
name
],
request
=
request
)
for
tag
in
eventlog
.
tag_set
.
all
()]
}
return
Response
(
rv
)
class
EventLogTagDetail
(
APIView
):
"""
Event Log Tag Detail Resource
"""
authentication_classes
=
(
LigoAuthentication
,)
permission_classes
=
(
IsAuthenticated
,)
def
get
(
self
,
request
,
graceid
,
n
,
tagname
):
try
:
event
=
Event
.
getByGraceid
(
graceid
)
eventlog
=
event
.
eventlog_set
.
order_by
(
"
created
"
).
all
()[
int
(
n
)]
except
Event
.
DoesNotExist
:
# XXX Real error message.
return
Response
(
"
Event does not exist.
"
,
status
=
status
.
HTTP_404_NOT_FOUND
)
except
:
# XXX Real error message.
return
Response
(
"
Log does not exist.
"
,
status
=
status
.
HTTP_404_NOT_FOUND
)
try
:
tag
=
eventlog
.
tag_set
.
filter
(
name
=
tagname
)[
0
]
# Serialize
return
Response
(
tagToDict
(
tag
,
event
=
event
,
n
=
n
,
request
=
request
))
except
:
return
Response
(
"
Tag not found.
"
,
status
=
status
.
HTTP_404_NOT_FOUND
)
def
put
(
self
,
request
,
graceid
,
n
,
tagname
):
logger
=
logging
.
getLogger
(
__name__
)
try
:
event
=
Event
.
getByGraceid
(
graceid
)
eventlog
=
event
.
eventlog_set
.
order_by
(
"
created
"
).
all
()[
int
(
n
)]
except
Event
.
DoesNotExist
:
# XXX Real error message.
return
Response
(
"
Event does not exist.
"
,
status
=
status
.
HTTP_404_NOT_FOUND
)
except
:
# XXX Real error message.
return
Response
(
"
Log does not exist.
"
,
status
=
status
.
HTTP_404_NOT_FOUND
)
try
:
# Has this tag-eventlog relationship already been created? If so, kick out.
# Actually, adding the eventlog to the tag would not hurt anything--no
# duplicate entry would be made in the database. However, we don't want
# an extra log entry, or a deceptive HTTP response (i.e., one telling the
# client that the creation was sucessful when, in fact, the database
# was unchanged.
tag
=
eventlog
.
tag_set
.
filter
(
name
=
tagname
)[
0
]
msg
=
"
Log already has tag %s
"
%
unicode
(
tag
)
return
Response
(
msg
,
status
=
status
.
HTTP_409_CONFLICT
)
except
:
# Look for the tag. If it doesn't already exist, create it.
try
:
tag
=
Tag
.
objects
.
filter
(
name
=
tagname
)[
0
]
except
:
displayName
=
request
.
DATA
.
get
(
'
filename
'
)
tag
=
Tag
(
name
=
tagname
,
displayName
=
displayName
)
tag
.
save
()
# Now add the log message to this tag.
tag
.
eventlogs
.
add
(
eventlog
)
# Create a log entry to document the tag creation.
msg
=
"
Tagged message %s: %s
"
%
(
n
,
tagname
)
logentry
=
EventLog
(
event
=
event
,
issuer
=
request
.
ligouser
,
comment
=
msg
)
logentry
.
save
()
return
Response
(
"
Tag created.
"
,
status
=
status
.
HTTP_201_CREATED
)
def
delete
(
self
,
request
,
graceid
,
n
,
tagname
):
try
:
event
=
Event
.
getByGraceid
(
graceid
)
eventlog
=
event
.
eventlog_set
.
order_by
(
"
created
"
).
all
()[
int
(
n
)]
except
Event
.
DoesNotExist
:
# XXX Real error message.
return
Response
(
"
Event does not exist.
"
,
status
=
status
.
HTTP_404_NOT_FOUND
)
except
:
# XXX Real error message.
return
Response
(
"
Log does not exist.
"
,
status
=
status
.
HTTP_404_NOT_FOUND
)
try
:
tag
=
eventlog
.
tag_set
.
filter
(
name
=
tagname
)[
0
]
tag
.
delete
()
return
Response
(
"
Tag deleted.
"
,
status
=
status
.
HTTP_200_OK
)
# Create a log entry to document the tag creation.
msg
=
"
Removed tag %s for message %s.
"
%
(
tagname
,
n
)
logentry
=
EventLog
(
event
=
event
,
issuer
=
request
.
ligouser
,
comment
=
msg
)
logentry
.
save
()
except
:
return
Response
(
"
Tag not found.
"
,
status
=
status
.
HTTP_404_NOT_FOUND
)
#==================================================================
# Root Resource
...
...
@@ -583,6 +836,17 @@ class GracedbRoot(APIView):
slot
=
slot
.
replace
(
"
G1200
"
,
"
{graceid}
"
)
slot
=
slot
.
replace
(
"
slotname
"
,
"
{slotname}
"
)
taglist
=
reverse
(
"
eventlogtag-list
"
,
args
=
[
"
G1200
"
,
"
0
"
],
request
=
request
)
taglist
=
taglist
.
replace
(
"
G1200
"
,
"
{graceid}
"
)
taglist
=
taglist
.
replace
(
"
0
"
,
"
{n}
"
)
tag
=
reverse
(
"
eventlogtag-detail
"
,
args
=
[
"
G1200
"
,
"
0
"
,
"
tagname
"
],
request
=
request
)
tag
=
tag
.
replace
(
"
G1200
"
,
"
{graceid}
"
)
tag
=
tag
.
replace
(
"
0
"
,
"
{n}
"
)
tag
=
tag
.
replace
(
"
tagname
"
,
"
{tagname}
"
)
# XXX Need a template for the tag list?
templates
=
{
"
event-detail-template
"
:
detail
,
"
event-log-template
"
:
log
,
...
...
@@ -590,6 +854,8 @@ class GracedbRoot(APIView):
"
files-template
"
:
files
,
"
filemeta-template
"
:
filemeta
,
"
slot-template
"
:
slot
,
"
tag-template
"
:
tag
,
"
taglist-template
"
:
taglist
,
}
return
Response
({
...
...
@@ -884,10 +1150,25 @@ class EventSlot(APIView):
slot
=
Slot
.
objects
.
filter
(
event
=
event
).
filter
(
name
=
slotname
)[
0
]
slot
.
value
=
filename
slot
.
save
()
# Create a log entry to document the slot update.
msg
=
"
Updated slot %s with file
"
%
slotname
logentry
=
EventLog
(
event
=
event
,
issuer
=
request
.
ligouser
,
filename
=
tmpFilename
,
comment
=
msg
)
logentry
.
save
()
except
:
# Create the slot.
slot
=
Slot
(
event
=
event
,
name
=
slotname
,
value
=
filename
)
slot
.
save
()
# Create a log entry to document the slot creation.
msg
=
"
Created slot %s with file
"
%
slotname
logentry
=
EventLog
(
event
=
event
,
issuer
=
request
.
ligouser
,
filename
=
tmpFilename
,
comment
=
msg
)
logentry
.
save
()
return
Response
(
"
Slot created or updated.
"
,
status
=
status
.
HTTP_201_CREATED
)
# Delete a slot.
...
...
@@ -909,5 +1190,12 @@ class EventSlot(APIView):
status
=
status
.
HTTP_404_NOT_FOUND
)
slot
.
delete
()
# Create a log entry to document the slot destruction.
msg
=
"
Deleted slot %s
"
%
slotname
logentry
=
EventLog
(
event
=
event
,
issuer
=
request
.
ligouser
,
comment
=
msg
)
logentry
.
save
()
return
Response
(
"
Slot deleted.
"
,
status
=
status
.
HTTP_200_OK
)
This diff is collapsed.
Click to expand it.
gracedb/models.py
+
54
−
1
View file @
6db1dbcb
...
...
@@ -171,6 +171,25 @@ class Event(models.Model):
def
__unicode__
(
self
):
return
self
.
graceid
()
# Return a list of distinct tags associated with the log messages of this
# event.
def
getAvailableTags
(
self
):
tagset_list
=
[
log
.
tag_set
.
all
()
for
log
in
self
.
eventlog_set
.
all
()]
taglist
=
[]
for
tagset
in
tagset_list
:
for
tag
in
tagset
:
taglist
.
append
(
tag
)
# Eliminate duplicates
return
list
(
set
(
taglist
))
def
getLogsForTag
(
self
,
tagname
):
loglist
=
[]
for
log
in
self
.
eventlog_set
.
all
():
for
tag
in
log
.
tag_set
.
all
():
if
tag
.
name
==
tagname
:
loglist
.
append
(
log
)
return
loglist
class
EventLog
(
models
.
Model
):
class
Meta
:
ordering
=
[
"
-created
"
]
...
...
@@ -191,6 +210,16 @@ class EventLog(models.Model):
# XXX hacky
return
self
.
filename
and
self
.
filename
[
-
3
:].
lower
()
in
[
'
png
'
,
'
gif
'
,
'
jpg
'
]
def
getN
(
self
):
# XXX also hacky?
# I think it would still work if some logs were removed from the database.
logset
=
self
.
event
.
eventlog_set
.
order_by
(
"
created
"
)
# XXX This actually evaluates the queryset. This may be a problem if
# there are a huge number of log messages for this event and they
# take up a lot of memory
logset
=
list
(
logset
)
return
logset
.
index
(
self
)
class
Labelling
(
models
.
Model
):
event
=
models
.
ForeignKey
(
Event
)
label
=
models
.
ForeignKey
(
Label
)
...
...
@@ -238,8 +267,32 @@ class MultiBurstEvent(Event):
ligo_angle
=
models
.
FloatField
(
null
=
True
)
ligo_angle_sig
=
models
.
FloatField
(
null
=
True
)
## Slots (user-defined event attributes)
## Tags (user-defined log message attributes)
class
Tag
(
models
.
Model
):
"""
Slot Model
"""
# XXX Does the tag need to have a submitter column?
# No, because creating a tag will generate a log message.
# For the same reason, a timstamp is not necessary.
eventlogs
=
models
.
ManyToManyField
(
EventLog
)
name
=
models
.
CharField
(
max_length
=
100
)
displayName
=
models
.
CharField
(
max_length
=
200
,
null
=
True
)
def
__unicode__
(
self
):
if
self
.
displayName
:
return
self
.
displayName
else
:
return
self
.
name
def
getEvents
(
self
):
# XXX Any way of doing this with filters?
# We would need to filter for a non-null intersection of the
# set of log messages in the event with the set of log
# messages in the tag.
eventlist
=
[
log
.
event
for
log
in
self
.
eventlogs
.
all
()]
return
list
(
set
(
eventlist
))
## XXX Get rid of the slots. Probably.
class
Slot
(
models
.
Model
):
"""
Slot Model
"""
# Does the slot need to have a submitter column?
...
...
This diff is collapsed.
Click to expand it.
gracedb/urls_rest.py
+
17
−
0
View file @
6db1dbcb
...
...
@@ -5,6 +5,9 @@ from django.conf.urls.defaults import patterns, url
from
gracedb.api
import
GracedbRoot
from
gracedb.api
import
EventList
,
EventDetail
from
gracedb.api
import
EventLogList
,
EventLogDetail
from
gracedb.api
import
TagList
,
TagDetail
from
gracedb.api
import
EventTagList
,
EventTagDetail
from
gracedb.api
import
EventLogTagList
,
EventLogTagDetail
from
gracedb.api
import
EventSlot
from
gracedb.api
import
Files
,
FileMeta
from
gracedb.api
import
EventNeighbors
,
EventLabel
...
...
@@ -27,6 +30,20 @@ urlpatterns = patterns('gracedb.api',
url
(
r
'
events/(?P<graceid>[GEHT]\d+)/log/(?P<n>\d+)$
'
,
EventLogDetail
.
as_view
(),
name
=
'
eventlog-detail
'
),
# Tag Resources
url
(
r
'
^tag/$
'
,
TagList
.
as_view
(),
name
=
'
tag-list
'
),
url
(
r
'
^tag/(?P<tagname>\w+)$
'
,
TagDetail
.
as_view
(),
name
=
'
tag-detail
'
),
url
(
r
'
events/(?P<graceid>[GEHT]\d+)/tag/$
'
,
EventTagList
.
as_view
(),
name
=
'
eventtag-list
'
),
url
(
r
'
events/(?P<graceid>[GEHT]\d+)/tag/(?P<tagname>\w+)$
'
,
EventTagDetail
.
as_view
(),
name
=
'
eventtag-detail
'
),
url
(
r
'
events/(?P<graceid>[GEHT]\d+)/log/(?P<n>\d+)/tag/$
'
,
EventLogTagList
.
as_view
(),
name
=
'
eventlogtag-list
'
),
url
(
r
'
events/(?P<graceid>[GEHT]\d+)/log/(?P<n>\d+)/tag/(?P<tagname>\w+)$
'
,
EventLogTagDetail
.
as_view
(),
name
=
'
eventlogtag-detail
'
),
# Event File Resources
# events/{graceid}/files/[{filename}[/{version}]]
url
(
r
'
^events/(?P<graceid>\w[\d]+)/files/(?P<filename>.+)?$
'
,
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment