Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
N
NACSOS Core
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
MCC APSIS
NACSOS
NACSOS Core
Commits
230c52d9
Commit
230c52d9
authored
2 years ago
by
Tim Repke
Browse files
Options
Downloads
Patches
Plain Diff
add several annotation related endpoints
parent
800192d4
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
config/logging.conf
+4
-0
4 additions, 0 deletions
config/logging.conf
server/api/__init__.py
+0
-1
0 additions, 1 deletion
server/api/__init__.py
server/api/routes/annotations.py
+96
-21
96 additions, 21 deletions
server/api/routes/annotations.py
with
100 additions
and
22 deletions
config/logging.conf
+
4
−
0
View file @
230c52d9
...
...
@@ -44,6 +44,10 @@ loggers:
handlers
: [
default
]
level
:
DEBUG
propagate
:
no
nacsos_data
:
handlers
: [
default
]
level
:
DEBUG
propagate
:
no
root
:
level
:
DEBUG
handlers
: [
default
]
\ No newline at end of file
This diff is collapsed.
Click to expand it.
server/api/__init__.py
+
0
−
1
View file @
230c52d9
...
...
@@ -12,7 +12,6 @@ router = APIRouter()
# route for testing / checking the service is reachable
router
.
include_router
(
ping
.
router
,
prefix
=
'
/ping
'
)
# route to fetch, manage, submit item annotations
router
.
include_router
(
annotations
.
router
,
prefix
=
'
/annotations
'
)
...
...
This diff is collapsed.
Click to expand it.
server/api/routes/annotations.py
+
96
−
21
View file @
230c52d9
from
fastapi
import
APIRouter
,
Depends
from
fastapi
import
APIRouter
,
Depends
,
HTTPException
,
status
as
http_status
from
nacsos_data.models.annotations
import
AnnotationTaskModel
,
AnnotationTaskLabel
,
AnnotationTaskLabelChoice
,
\
AssignmentScopeModel
,
AssignmentModel
AssignmentScopeModel
,
AssignmentModel
,
AssignmentStatus
from
nacsos_data.models.items
import
ItemModel
from
nacsos_data.models.items.twitter
import
TwitterItemModel
from
nacsos_data.db.crud.items.twitter
import
read_tweet_by_item_id
...
...
@@ -8,9 +8,15 @@ from nacsos_data.db.crud.annotations import \
read_assignments_for_scope_for_user
,
\
read_assignment_scopes_for_project_for_user
,
\
read_annotations_for_assignment
,
\
read_assignment_scope
,
\
read_next_assignment_for_scope_for_user
,
\
read_next_open_assignment_for_scope_for_user
,
\
read_annotation_task
,
\
read_annotation_tasks_for_project
,
\
read_assignment
,
\
upsert_annotations
,
\
UserProjectAssignmentScope
from
nacsos_data.util.annotations.validation
import
merge_task_and_annotations
,
annotated_task_to_annotations
from
pydantic
import
BaseModel
from
server.util.security
import
UserPermissionChecker
...
...
@@ -19,8 +25,13 @@ from server.data import db_engine
router
=
APIRouter
()
class
Annotat
ion
Item
(
BaseModel
):
class
Annotat
ed
Item
(
BaseModel
):
task
:
AnnotationTaskModel
assignment
:
AssignmentModel
class
AnnotationItem
(
AnnotatedItem
):
scope
:
AssignmentScopeModel
item
:
ItemModel
|
TwitterItemModel
...
...
@@ -46,22 +57,67 @@ async def get_task_definitions_for_project(project_id: str) -> list[AnnotationTa
return
await
read_annotation_tasks_for_project
(
project_id
=
project_id
,
engine
=
db_engine
)
@router.get
(
'
/annotate/next/{
project_id}/{
assignment_
scope_
id}
'
,
response_model
=
AnnotationItem
)
@router.get
(
'
/annotate/next/{
assignment_scope_id}/{current_
assignment_id}
'
,
response_model
=
AnnotationItem
)
async
def
get_next_assignment_for_scope_for_user
(
assignment_scope_id
:
str
,
permissions
=
Depends
(
UserPermissionChecker
(
'
annotations_edit
'
))):
assignments
=
await
read_assignments_for_scope_for_user
(
assignment_scope_id
=
assignment_scope_id
,
user_id
=
permissions
.
user
.
user_id
,
engine
=
db_engine
)
# FIXME: magically find the next-to-annotate id
item
=
await
read_tweet_by_item_id
(
assignments
[
0
].
item
,
engine
=
db_engine
)
return
AnnotationItem
(
task
=
ATM
(
'
668529f5-1c54-44ef-b665-290ad3632f0d
'
),
item
=
tweet
)
current_assignment_id
:
str
,
permissions
=
Depends
(
UserPermissionChecker
(
'
annotations_read
'
))):
# FIXME response for "last in list"
assignment
=
await
read_next_assignment_for_scope_for_user
(
current_assignment_id
=
current_assignment_id
,
assignment_scope_id
=
assignment_scope_id
,
user_id
=
permissions
.
user
.
user_id
,
engine
=
db_engine
)
scope
=
await
read_assignment_scope
(
assignment_scope_id
=
assignment_scope_id
,
engine
=
db_engine
)
task
=
await
read_annotation_task
(
annotation_task_id
=
assignment
.
task_id
,
engine
=
db_engine
)
annotations
=
await
read_annotations_for_assignment
(
assignment_id
=
assignment
.
assignment_id
,
engine
=
db_engine
)
_
,
task
=
merge_task_and_annotations
(
annotation_task
=
task
,
annotations
=
annotations
)
# FIXME: get any item type, not just tweets
item
=
await
read_tweet_by_item_id
(
item_id
=
assignment
.
item_id
,
engine
=
db_engine
)
return
AnnotationItem
(
task
=
task
,
assignment
=
assignment
,
scope
=
scope
,
item
=
item
)
@router.get
(
'
/annotate/next/{assignment_scope_id}
'
,
response_model
=
AnnotationItem
)
async
def
get_next_open_assignment_for_scope_for_user
(
assignment_scope_id
:
str
,
permissions
=
Depends
(
UserPermissionChecker
(
'
annotations_read
'
))):
# FIXME response for "all done"
assignment
=
await
read_next_open_assignment_for_scope_for_user
(
assignment_scope_id
=
assignment_scope_id
,
user_id
=
permissions
.
user
.
user_id
,
engine
=
db_engine
)
scope
=
await
read_assignment_scope
(
assignment_scope_id
=
assignment_scope_id
,
engine
=
db_engine
)
task
=
await
read_annotation_task
(
annotation_task_id
=
assignment
.
task_id
,
engine
=
db_engine
)
annotations
=
await
read_annotations_for_assignment
(
assignment_id
=
assignment
.
assignment_id
,
engine
=
db_engine
)
_
,
task
=
merge_task_and_annotations
(
annotation_task
=
task
,
annotations
=
annotations
)
# FIXME: get any item type, not just tweets
item
=
await
read_tweet_by_item_id
(
item_id
=
assignment
.
item_id
,
engine
=
db_engine
)
return
AnnotationItem
(
task
=
task
,
assignment
=
assignment
,
scope
=
scope
,
item
=
item
)
@router.get
(
'
/annotate/assignment/{assignment_id}
'
,
response_model
=
AnnotationItem
)
async
def
get_assignment
(
assignment_id
:
str
,
permissions
=
Depends
(
UserPermissionChecker
(
'
annotations_read
'
))):
assignment
=
await
read_assignment
(
assignment_id
=
assignment_id
,
engine
=
db_engine
)
assert
assignment
.
user_id
==
permissions
.
user
.
user_id
scope
=
await
read_assignment_scope
(
assignment_scope_id
=
assignment
.
assignment_scope_id
,
engine
=
db_engine
)
task
=
await
read_annotation_task
(
annotation_task_id
=
assignment
.
task_id
,
engine
=
db_engine
)
annotations
=
await
read_annotations_for_assignment
(
assignment_id
=
assignment_id
,
engine
=
db_engine
)
_
,
task
=
merge_task_and_annotations
(
annotation_task
=
task
,
annotations
=
annotations
)
# FIXME: get any item type, not just tweets
item
=
await
read_tweet_by_item_id
(
item_id
=
assignment
.
item_id
,
engine
=
db_engine
)
return
AnnotationItem
(
task
=
task
,
assignment
=
assignment
,
scope
=
scope
,
item
=
item
)
@router.get
(
'
/annotate/scopes/{project_id}
'
,
response_model
=
list
[
UserProjectAssignmentScope
])
async
def
get_assignment_scopes
(
project_id
:
str
,
permissions
=
Depends
(
UserPermissionChecker
(
'
annotations_read
'
)))
\
async
def
get_assignment_scopes_for_user
(
project_id
:
str
,
permissions
=
Depends
(
UserPermissionChecker
(
'
annotations_read
'
)))
\
->
list
[
UserProjectAssignmentScope
]:
scopes
=
await
read_assignment_scopes_for_project_for_user
(
project_id
=
project_id
,
user_id
=
permissions
.
user
.
user_id
,
...
...
@@ -69,23 +125,42 @@ async def get_assignment_scopes(project_id: str, permissions=Depends(UserPermiss
return
scopes
@router.get
(
'
/annotate/assignments/{
project_id}/{
assignment_scope_id}
'
,
response_model
=
list
[
AssignmentModel
])
@router.get
(
'
/annotate/assignments/{assignment_scope_id}
'
,
response_model
=
list
[
AssignmentModel
])
async
def
get_assignments
(
assignment_scope_id
:
str
,
permissions
=
Depends
(
UserPermissionChecker
(
'
annotations_read
'
)))
\
->
list
[
AssignmentModel
]:
# FIXME: would be more elegant to get the project ID indirectly via the assignment_scope
# rather than passing it as a redundant parameter
assignments
=
await
read_assignments_for_scope_for_user
(
assignment_scope_id
=
assignment_scope_id
,
user_id
=
permissions
.
user
.
user_id
,
engine
=
db_engine
)
return
assignments
@router.get
(
'
/annotate/annotations/{
project_id}/{
assignment_scope_id}
'
,
response_model
=
list
[
AssignmentModel
])
@router.get
(
'
/annotate/annotations/{assignment_scope_id}
'
,
response_model
=
list
[
AssignmentModel
])
async
def
get_annotations
(
assignment_scope_id
:
str
,
permissions
=
Depends
(
UserPermissionChecker
(
'
annotations_read
'
)))
\
->
list
[
AssignmentModel
]:
# FIXME: would be more elegant to get the project ID indirectly via the assignment_scope
# rather than passing it as a redundant parameter
assignments
=
await
read_assignments_for_scope_for_user
(
assignment_scope_id
=
assignment_scope_id
,
user_id
=
permissions
.
user
.
user_id
,
engine
=
db_engine
)
return
assignments
@router.post
(
'
/annotate/save
'
)
async
def
save_annotation
(
annotated_item
:
AnnotatedItem
,
permissions
=
Depends
(
UserPermissionChecker
(
'
annotations_read
'
)))
->
AssignmentStatus
:
# double-check, that the supposed assignment actually exists
assignment_db
=
await
read_assignment
(
assignment_id
=
annotated_item
.
assignment
.
assignment_id
,
engine
=
db_engine
)
if
permissions
.
user
.
user_id
==
assignment_db
.
user_id
\
and
str
(
assignment_db
.
assignment_scope_id
)
==
annotated_item
.
assignment
.
assignment_scope_id
\
and
str
(
assignment_db
.
item_id
)
==
annotated_item
.
assignment
.
item_id
\
and
str
(
assignment_db
.
task_id
)
==
annotated_item
.
assignment
.
task_id
:
print
(
'
permission yay
'
)
annotations
=
annotated_task_to_annotations
(
annotated_item
.
task
)
status
=
await
upsert_annotations
(
annotations
=
annotations
,
assignment_id
=
annotated_item
.
assignment
.
assignment_id
,
engine
=
db_engine
)
return
status
else
:
raise
HTTPException
(
status_code
=
http_status
.
HTTP_403_FORBIDDEN
,
detail
=
f
'
The combination of project, assignment, user, task, and item is invalid.
'
,
)
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