Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No public description #295

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 11 additions & 41 deletions src/eagle_eye/app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,19 +156,15 @@
"""A decorator function checking for a valid session token.

Checks for a valid session token before executing the given
decorated_func, or redirects to the default route for sign-in if the
decorated_func, or redirect to the default route for sign-in if the
session token is invalid.

If the session token is valid, passes the `email` field from the
session token to the decorated method.
"""

def wrapper(*args, **kwargs):
session_token = request.cookies.get('sessionToken')
if session_token:
try:
decoded_token = auth.verify_session_cookie(session_token)
kwargs['user_email'] = decoded_token['email']
return decorated_func(*args, **kwargs)
except (
auth.InvalidIdTokenError,
Expand Down Expand Up @@ -217,10 +213,8 @@

@app.route('/projects', methods=['GET'])
@require_authentication
def homepage(user_email):
def homepage():
"""Returns the eagleeye homepage."""
del user_email # Unused

is_admin = _check_is_admin(request.cookies.get('sessionToken'))

all_projects_snapshot = firestore_db.collection('projects').get()
Expand Down Expand Up @@ -387,16 +381,11 @@
'/project/<path:project_id>/task/<path:example_id>', methods=['POST']
)
@require_authentication
def submit_task(project_id, example_id, user_email):
def submit_task(project_id, example_id):
"""Handles the task submission POST request.

Writes the labeled task to Firestore. Note that this overwrites the
existing label, if one is currently set.

Args:
project_id: project id
example_id: example id
user_email: email of the labeler
"""
print(f'handling submit task for example id: {example_id}')
assessment = request.form.get('assessment')
Expand All @@ -406,17 +395,14 @@

task = get_task_from_db(firestore_db, project.project_id, example_id)
task.label = assessment
task.labeler = user_email
task.write_to_firestore(project.project_id, firestore_db)
return redirect(f'/project/{project.project_id}/next')

Check warning

Code scanning / CodeQL

URL redirection from remote source Medium

Untrusted URL redirection depends on a
user-provided value
.


@app.route('/project/<path:project_id>/task/<path:example_id>', methods=['GET'])
@require_authentication
def get_task(project_id, example_id, user_email):
def get_task(project_id, example_id):
"""Returns the task labeling page for the given project_id and example_id."""
del user_email # Unused

print(f'Returning task: {example_id}, in project: {project_id}')
project = get_project_from_db(firestore_db, project_id)
if not project:
Expand Down Expand Up @@ -454,7 +440,7 @@

@app.route('/project/<path:project_id>/next', methods=['GET'])
@require_authentication
def get_next_task(project_id, user_email):
def get_next_task(project_id):
"""Returns a currently unlabeled task, in a pseudo-random order.

If there are no remaining unlabeled tasks, redirects to the project
Expand All @@ -465,13 +451,7 @@
and introducing enough randomness such that multiple users
concurrently labeling tasks are unlikely to have duplicate tasks /
wasted effort.

Args:
project_id: project id
user_email: email of the labeler
"""
del user_email # Unused

LIMIT_TASK_COUNT_READS = 20
project = get_project_from_db(firestore_db, project_id)
if not project:
Expand All @@ -485,22 +465,20 @@
)
if len(unlabeled_tasks) <= 0:
print('project has no remaining tasks, redirect to summary.')
return redirect(f'/project/{project.project_id}/summary')

Check warning

Code scanning / CodeQL

URL redirection from remote source Medium

Untrusted URL redirection depends on a
user-provided value
.

next_task_index = random.randrange(0, len(unlabeled_tasks))
next_task = unlabeled_tasks[next_task_index]

next_example_id = next_task.get('exampleId')
print(f'returning next example id: {next_example_id}')
return redirect(f'/project/{project.project_id}/task/{next_example_id}')

Check warning

Code scanning / CodeQL

URL redirection from remote source Medium

Untrusted URL redirection depends on a
user-provided value
.


@app.route('/project/<path:project_id>/summary', methods=['GET'])
@require_authentication
def summary(project_id, user_email):
def summary(project_id):
"""Returns the project summary page."""
del user_email # Unused

is_admin = _check_is_admin(request.cookies.get('sessionToken'))

project = get_project_from_db(firestore_db, project_id)
Expand Down Expand Up @@ -583,10 +561,8 @@

@app.route('/project/<path:project_id>/task_table', methods=['GET'])
@require_authentication
def task_table(project_id, user_email):
def task_table(project_id):
"""Returns a page with a paginated list of tasks for the project."""
del user_email # Unused

page = request.args.get('page', 1, type=int)
label = request.args.get('label', '', type=str)
project = get_project_from_db(firestore_db, project_id)
Expand Down Expand Up @@ -619,10 +595,8 @@

@app.route('/project/<path:project_id>/download_csv', methods=['GET'])
@require_authentication
def download_csv(project_id, user_email):
def download_csv(project_id):
"""Returns a csv containing the labeled tasks for the project."""
del user_email # Unused

print(f'Producing results csv for project: {project_id}')
project = get_project_from_db(firestore_db, project_id)
if not project:
Expand All @@ -631,15 +605,11 @@
filename = f'labeled_tasks_{project.project_id}'
df = pd.DataFrame(
[
(
task_dict.get('exampleId'),
task_dict.get('label'),
task_dict.get('labeler', ''),
)
(task.get('exampleId'), label)
for task in firestore_db.collection(project.project_id).stream()
if ((task_dict := task.to_dict()).get('label'))
if (label := task.get('label'))
],
columns=['example_id', 'string_label', 'labeler'],
columns=['example_id', 'string_label'],
)
output_bytes = io.BytesIO()
df.to_csv(output_bytes, index=False)
Expand Down
12 changes: 4 additions & 8 deletions src/eagle_eye/app/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,11 @@ def get_task_from_db(firestore_db, project_id, example_id):
task_firestore = (
firestore_db.collection(project_id).document(example_id).get()
)
task_dict = task_firestore.to_dict()
return Task(
example_id,
task_dict.get('preImage'),
task_dict.get('postImage'),
task_dict.get('label'),
task_dict.get('labeler', ''),
task_firestore.get('preImage'),
task_firestore.get('postImage'),
task_firestore.get('label'),
)


Expand Down Expand Up @@ -70,13 +68,12 @@ def normalize_image_url_suffix(image_url):
class Task:
"""A Task data type."""

def __init__(self, example_id, pre_image, post_image, label='', labeler=''):
def __init__(self, example_id, pre_image, post_image, label=''):
"""Initializes a Task object."""
self.example_id = example_id
self.pre_image = pre_image
self.post_image = post_image
self.label = label
self.labeler = labeler

def write_to_firestore(self, project_id, firestore_db):
"""Writes the Task to the given project_id firestore collection."""
Expand All @@ -87,7 +84,6 @@ def write_to_firestore(self, project_id, firestore_db):
'preImage': self.pre_image,
'postImage': self.post_image,
'label': self.label,
'labeler': self.labeler,
}
firestore_db.collection(project_id).document(self.example_id).set(
firestore_format
Expand Down
Loading