コード例 #1
0
ファイル: test_cache_helpers.py プロジェクト: lsuttle/pybossa
    def test_n_available_tasks_include_gold_task(self):
        """Test n_available_tasks returns 0 for user if he has
        submitted taskruns for all the tasks"""
        project = ProjectFactory.create()
        task = TaskFactory.create(project=project, calibration=1)

        n_available_tasks_include_gold = helpers.n_available_tasks(
            project.id, include_gold_task=True)
        n_available_tasks_exclude_gold = helpers.n_available_tasks(project.id)

        assert task.state != 'completed', task.state
        assert n_available_tasks_include_gold == 1, n_available_tasks_include_gold
        assert n_available_tasks_exclude_gold == 0, n_available_tasks_exclude_gold
コード例 #2
0
def user_progress(project_id=None, short_name=None):
    """API endpoint for user progress.

    Return a JSON object with two fields regarding the tasks for the user:
        { 'done': 10,
          'total: 100,
          'remaining': 90
        }
       This will mean that the user has done a 10% of the available tasks for
       him and 90 tasks are yet to be submitted

    """
    if current_user.is_anonymous():
        return abort(401)
    if project_id or short_name:
        if short_name:
            project = project_repo.get_by_shortname(short_name)
        elif project_id:
            project = project_repo.get(project_id)

        if project:
            # For now, keep this version, but wait until redis cache is used here for task_runs too
            query_attrs = dict(project_id=project.id)
            query_attrs['user_id'] = current_user.id
            taskrun_count = task_repo.count_task_runs_with(**query_attrs)
            num_available_tasks = n_available_tasks(project.id,
                                                    current_user.id)
            tmp = dict(done=taskrun_count,
                       total=n_tasks(project.id),
                       remaining=num_available_tasks)
            return Response(json.dumps(tmp), mimetype="application/json")
        else:
            return abort(404)
    else:  # pragma: no cover
        return abort(404)
コード例 #3
0
ファイル: test_cache_helpers.py プロジェクト: lsuttle/pybossa
    def test_n_available_tasks_no_tasks(self):
        """Test n_available_tasks returns 0 for user if the project
        has no tasks"""
        project = ProjectFactory.create()

        n_available_tasks = helpers.n_available_tasks(project.id)

        assert n_available_tasks == 0, n_available_tasks
コード例 #4
0
    def test_n_available_tasks_no_tasks_authenticated_user(self):
        """Test n_available_tasks returns 0 for authenticated user if the project
        has no tasks"""
        project = ProjectFactory.create()

        n_available_tasks = helpers.n_available_tasks(project.id, user_id=1)

        assert n_available_tasks == 0, n_available_tasks
コード例 #5
0
    def test_n_available_tasks_no_tasks_anonymous_user(self):
        """Test n_available_tasks returns 0 for anonymous user if the app
        has no tasks"""
        app = AppFactory.create()

        n_available_tasks = helpers.n_available_tasks(app.id, user_ip='127.0.0.1')

        assert n_available_tasks == 0, n_available_tasks
コード例 #6
0
    def test_n_available_tasks_no_tasks_authenticated_user(self):
        """Test n_available_tasks returns 0 for authenticated user if the app
        has no tasks"""
        app = AppFactory.create()

        n_available_tasks = helpers.n_available_tasks(app.id, user_id=1)

        assert n_available_tasks == 0, n_available_tasks
コード例 #7
0
    def test_n_available_tasks_no_tasks_anonymous_user(self):
        """Test n_available_tasks returns 0 for anonymous user if the project
        has no tasks"""
        project = ProjectFactory.create()

        n_available_tasks = helpers.n_available_tasks(project.id, user_ip='127.0.0.1')

        assert n_available_tasks == 0, n_available_tasks
コード例 #8
0
    def test_n_available_tasks_no_tasks_anonymous_user(self):
        """Test n_available_tasks returns 0 for anonymous user if the project
        has no tasks"""
        project = ProjectFactory.create()

        n_available_tasks = helpers.n_available_tasks(project.id, user_ip='127.0.0.1')

        assert n_available_tasks == 0, n_available_tasks
コード例 #9
0
    def test_n_available_tasks_no_tasks_authenticated_user(self):
        """Test n_available_tasks returns 0 for authenticated user if the project
        has no tasks"""
        project = ProjectFactory.create()

        n_available_tasks = helpers.n_available_tasks(project.id, user_id=1)

        assert n_available_tasks == 0, n_available_tasks
コード例 #10
0
ファイル: test_cache_helpers.py プロジェクト: fesp21/pybossa
    def test_n_available_tasks_no_taskruns_anonymous_user(self):
        """Test n_available_tasks returns 1 for anonymous user
        if there are no taskruns"""
        app = AppFactory.create()
        task = TaskFactory.create(app=app)

        n_available_tasks = helpers.n_available_tasks(app.id, user_ip='127.0.0.1')

        assert n_available_tasks == 1, n_available_tasks
コード例 #11
0
ファイル: test_cache_helpers.py プロジェクト: fesp21/pybossa
    def test_n_available_tasks_no_taskruns_authenticated_user(self):
        """Test n_available_tasks returns 1 for authenticated user
        if there are no taskruns"""
        app = AppFactory.create()
        task = TaskFactory.create(app=app)

        n_available_tasks = helpers.n_available_tasks(app.id, user_id=1)

        assert n_available_tasks == 1, n_available_tasks
コード例 #12
0
    def test_n_available_tasks_all_tasks_completed_authenticated_user(self):
        """Test n_available_tasks returns 0 for authenticated user if all the
        tasks are completed"""
        app = AppFactory.create()
        task = TaskFactory.create(app=app, state='completed')

        n_available_tasks = helpers.n_available_tasks(app.id, user_id=1)

        assert n_available_tasks == 0, n_available_tasks
コード例 #13
0
    def test_n_available_tasks_no_taskruns_authenticated_user(self):
        """Test n_available_tasks returns 1 for authenticated user
        if there are no taskruns"""
        app = AppFactory.create()
        task = TaskFactory.create(app=app)

        n_available_tasks = helpers.n_available_tasks(app.id, user_id=1)

        assert n_available_tasks == 1, n_available_tasks
コード例 #14
0
ファイル: test_cache_helpers.py プロジェクト: lsuttle/pybossa
    def test_n_available_tasks_all_tasks_completed(self):
        """Test n_available_tasks returns 0 for user if all the
        tasks are completed"""
        project = ProjectFactory.create()
        task = TaskFactory.create(project=project, state='completed')

        n_available_tasks = helpers.n_available_tasks(project.id)

        assert n_available_tasks == 0, n_available_tasks
コード例 #15
0
    def test_n_available_tasks_no_taskruns_anonymous_user(self):
        """Test n_available_tasks returns 1 for anonymous user
        if there are no taskruns"""
        project = ProjectFactory.create()
        task = TaskFactory.create(project=project)

        n_available_tasks = helpers.n_available_tasks(project.id, user_ip='127.0.0.1')

        assert n_available_tasks == 1, n_available_tasks
コード例 #16
0
    def test_n_available_tasks_no_taskruns_anonymous_user(self):
        """Test n_available_tasks returns 1 for anonymous user
        if there are no taskruns"""
        project = ProjectFactory.create()
        task = TaskFactory.create(project=project)

        n_available_tasks = helpers.n_available_tasks(project.id, user_ip='127.0.0.1')

        assert n_available_tasks == 1, n_available_tasks
コード例 #17
0
    def test_n_available_tasks_all_tasks_completed_authenticated_user(self):
        """Test n_available_tasks returns 0 for authenticated user if all the
        tasks are completed"""
        project = ProjectFactory.create()
        task = TaskFactory.create(project=project, state='completed')

        n_available_tasks = helpers.n_available_tasks(project.id, user_id=1)

        assert n_available_tasks == 0, n_available_tasks
コード例 #18
0
ファイル: test_cache_helpers.py プロジェクト: lsuttle/pybossa
    def test_n_available_tasks_no_taskruns(self):
        """Test n_available_tasks returns 1 for authenticated user
        if there are no taskruns"""
        project = ProjectFactory.create()
        task = TaskFactory.create(project=project)

        n_available_tasks = helpers.n_available_tasks(project.id)

        assert n_available_tasks == 1, n_available_tasks
コード例 #19
0
    def test_n_available_tasks_all_tasks_completed_anonymous_user(self):
        """Test n_available_tasks returns 0 for anonymous user if all the
        tasks are completed"""
        project = ProjectFactory.create()
        task = TaskFactory.create(project=project, state='completed')

        n_available_tasks = helpers.n_available_tasks(project.id, user_ip='127.0.0.1')

        assert n_available_tasks == 0, n_available_tasks
コード例 #20
0
    def test_n_available_tasks_all_tasks_completed_anonymous_user(self):
        """Test n_available_tasks returns 0 for anonymous user if all the
        tasks are completed"""
        project = ProjectFactory.create()
        task = TaskFactory.create(project=project, state='completed')

        n_available_tasks = helpers.n_available_tasks(project.id, user_ip='127.0.0.1')

        assert n_available_tasks == 0, n_available_tasks
コード例 #21
0
    def test_n_available_tasks_no_taskruns_authenticated_user(self):
        """Test n_available_tasks returns 1 for authenticated user
        if there are no taskruns"""
        project = ProjectFactory.create()
        task = TaskFactory.create(project=project)

        n_available_tasks = helpers.n_available_tasks(project.id, user_id=1)

        assert n_available_tasks == 1, n_available_tasks
コード例 #22
0
    def test_n_available_tasks_task_answered_by_another_user(self):
        """Test n_available_tasks returns 1 for a user if another
        user has submitted taskruns for the task but he hasn't"""
        project = ProjectFactory.create()
        task = TaskFactory.create(project=project)
        user = UserFactory.create()
        taskrun = TaskRunFactory.create(task=task)

        n_available_tasks = helpers.n_available_tasks(project.id, user_id=user.id)
        assert n_available_tasks == 1, n_available_tasks
コード例 #23
0
    def test_n_available_tasks_no_taskruns_anonymous_user(self):
        """Test n_available_tasks returns 1 for anonymous user
        if there are no taskruns"""
        app = AppFactory.create()
        task = TaskFactory.create(app=app)

        n_available_tasks = helpers.n_available_tasks(app.id,
                                                      user_ip='127.0.0.1')

        assert n_available_tasks == 1, n_available_tasks
コード例 #24
0
    def test_n_available_tasks_some_task_answered_by_another_user(self):
        """Test n_available_tasks returns 1 for a user if another
        user has submitted taskruns for the task but he hasn't"""
        project = ProjectFactory.create()
        task = TaskFactory.create(project=project)
        user = UserFactory.create()
        taskrun = TaskRunFactory.create(task=task)

        n_available_tasks = helpers.n_available_tasks(project.id, user_id=user.id)
        assert n_available_tasks == 1, n_available_tasks
コード例 #25
0
    def test_n_available_tasks_all_tasks_answered_by_anonymous_user(self):
        """Test n_available_tasks returns 0 for anonymous user if he has
        submitted taskruns for all the tasks"""
        project = ProjectFactory.create()
        task = TaskFactory.create(project=project, n_answers=2)
        taskrun = AnonymousTaskRunFactory.create(task=task)

        n_available_tasks = helpers.n_available_tasks(project.id, user_ip=taskrun.user_ip)

        assert task.state != 'completed', task.state
        assert n_available_tasks == 0, n_available_tasks
コード例 #26
0
    def test_n_available_tasks_some_tasks_answered_by_authenticated_user(self):
        """Test n_available_tasks returns 1 for authenticated user if he has
        submitted taskruns for one of the tasks but there is still another task"""
        project = ProjectFactory.create()
        answered_task = TaskFactory.create(project=project)
        available_task = TaskFactory.create(project=project)
        user = UserFactory.create()
        taskrun = TaskRunFactory.create(task=answered_task, user=user)

        n_available_tasks = helpers.n_available_tasks(project.id, user_id=user.id)
        assert n_available_tasks == 1, n_available_tasks
コード例 #27
0
    def test_n_available_tasks_some_tasks_answered_by_authenticated_user(self):
        """Test n_available_tasks returns 1 for authenticated user if he has
        submitted taskruns for one of the tasks but there is still another task"""
        project = ProjectFactory.create()
        answered_task = TaskFactory.create(project=project)
        available_task = TaskFactory.create(project=project)
        user = UserFactory.create()
        taskrun = TaskRunFactory.create(task=answered_task, user=user)

        n_available_tasks = helpers.n_available_tasks(project.id, user_id=user.id)
        assert n_available_tasks == 1, n_available_tasks
コード例 #28
0
    def test_n_available_tasks_some_tasks_answered_by_anonymous_user(self):
        """Test n_available_tasks returns 1 for anonymous user if he has
        submitted taskruns for one of the tasks but there is still another task"""
        project = ProjectFactory.create()
        answered_task = TaskFactory.create(project=project)
        available_task = TaskFactory.create(project=project)
        taskrun = AnonymousTaskRunFactory.create(task=answered_task)

        n_available_tasks = helpers.n_available_tasks(project.id, user_ip=taskrun.user_ip)

        assert n_available_tasks == 1, n_available_tasks
コード例 #29
0
    def test_n_available_some_all_tasks_answered_by_anonymous_user(self):
        """Test n_available_tasks returns 1 for anonymous user if he has
        submitted taskruns for one of the tasks but there is still another task"""
        project = ProjectFactory.create()
        answered_task = TaskFactory.create(project=project)
        available_task = TaskFactory.create(project=project)
        taskrun = AnonymousTaskRunFactory.create(task=answered_task)

        n_available_tasks = helpers.n_available_tasks(project.id, user_ip=taskrun.user_ip)

        assert n_available_tasks == 1, n_available_tasks
コード例 #30
0
    def test_n_available_tasks_all_tasks_answered_by_anonymous_user(self):
        """Test n_available_tasks returns 0 for anonymous user if he has
        submitted taskruns for all the tasks"""
        project = ProjectFactory.create()
        task = TaskFactory.create(project=project, n_answers=2)
        taskrun = AnonymousTaskRunFactory.create(task=task)

        n_available_tasks = helpers.n_available_tasks(project.id, user_ip=taskrun.user_ip)

        assert task.state != 'completed', task.state
        assert n_available_tasks == 0, n_available_tasks
コード例 #31
0
    def test_n_available_tasks_all_tasks_answered_by_authenticated_user(self):
        """Test n_available_tasks returns 0 for authenticated user if he has
        submitted taskruns for all the tasks"""
        project = ProjectFactory.create()
        task = TaskFactory.create(project=project, n_answers=2)
        user = UserFactory.create()
        taskrun = TaskRunFactory.create(task=task, user=user)

        n_available_tasks = helpers.n_available_tasks(project.id, user_id=user.id)

        assert task.state != 'completed', task.state
        assert n_available_tasks == 0, n_available_tasks
コード例 #32
0
ファイル: __init__.py プロジェクト: bloomberg/pybossa
def user_progress(project_id=None, short_name=None):
    """API endpoint for user progress.

    Return a JSON object with four fields regarding the tasks for the user:
        { 'done': 10,
          'total: 100,
          'remaining': 90,
          'remaining_for_user': 45
        }
       This will mean that the user has done 10% of the available tasks for the
       project, 90 tasks are yet to be submitted and the user can access 45 of
       them based on user preferences.

    """
    if current_user.is_anonymous:
        return abort(401)
    if project_id or short_name:
        if short_name:
            project = project_repo.get_by_shortname(short_name)
        elif project_id:
            project = project_repo.get(project_id)

        if project:
            # For now, keep this version, but wait until redis cache is
            # used here for task_runs too
            query_attrs = dict(project_id=project.id, user_id=current_user.id)
            guidelines_updated = _guidelines_updated(project.id,
                                                     current_user.id)
            taskrun_count = task_repo.count_task_runs_with(**query_attrs)
            num_available_tasks = n_available_tasks(project.id,
                                                    include_gold_task=True)
            num_available_tasks_for_user = n_available_tasks_for_user(
                project, current_user.id)
            response = dict(done=taskrun_count,
                            total=n_tasks(project.id),
                            completed=n_completed_tasks(project.id),
                            remaining=num_available_tasks,
                            locked=len({
                                task["task_id"]
                                for task in get_locked_tasks(project)
                            }),
                            remaining_for_user=num_available_tasks_for_user,
                            quiz=current_user.get_quiz_for_project(project),
                            guidelines_updated=guidelines_updated)
            if current_user.admin or (current_user.subadmin and current_user.id
                                      in project.owners_ids):
                num_gold_tasks = n_unexpired_gold_tasks(project.id)
                response['available_gold_tasks'] = num_gold_tasks
            return Response(json.dumps(response), mimetype="application/json")
        else:
            return abort(404)
    else:  # pragma: no cover
        return abort(404)
コード例 #33
0
ファイル: test_cache_helpers.py プロジェクト: lsuttle/pybossa
    def test_n_available_tasks_all_tasks_answered_by_user(self):
        """Test n_available_tasks returns 0 for user if he has
        submitted taskruns for all the tasks"""
        user = UserFactory.create()
        project = ProjectFactory.create()
        task = TaskFactory.create(project=project, n_answers=2)
        taskrun = TaskRunFactory.create(task=task, user=user)

        n_available_tasks = helpers.n_available_tasks(project.id)

        assert task.state != 'completed', task.state
        assert n_available_tasks == 1, n_available_tasks
コード例 #34
0
    def test_n_available_tasks_all_tasks_answered_by_authenticated_user(self):
        """Test n_available_tasks returns 0 for authenticated user if he has
        submitted taskruns for all the tasks"""
        app = AppFactory.create()
        task = TaskFactory.create(app=app, n_answers=2)
        user = UserFactory.create()
        taskrun = TaskRunFactory.create(task=task, user=user)

        n_available_tasks = helpers.n_available_tasks(app.id, user_id=user.id)

        assert task.state != 'completed', task.state
        assert n_available_tasks == 0, n_available_tasks
コード例 #35
0
    def get_projects_report(self, base_url):
        results = project_repo.get_projects_report()
        projects = []

        for row in results:
            owners_ids = project_repo.get_by_shortname(
                row.short_name).owners_ids
            coowners = (co for co in user_repo.get_users(owners_ids)
                        if co.name != row.owner_name)
            num_available_tasks = n_available_tasks(row.id)
            coowner_names = '|'.join('{};{}'.format(co.name, co.email_addr)
                                     for co in coowners)
            if not coowner_names:
                coowner_names = 'None'
            has_completed = str(num_available_tasks == 0)
            project = OrderedDict([('id', row.id), ('name', row.name),
                                   ('short_name', row.short_name),
                                   ('url', base_url + row.short_name),
                                   ('description', row.description),
                                   ('long_description', row.long_description),
                                   ('created', row.created),
                                   ('owner_name', row.owner_name),
                                   ('owner_email', row.owner_email),
                                   ('coowners', coowner_names),
                                   ('category_name', row.category_name),
                                   ('allow_anonymous_contributors',
                                    row.allow_anonymous_contributors),
                                   ('password_protected',
                                    row.password_protected),
                                   ('webhook', row.webhook),
                                   ('scheduler', row.scheduler),
                                   ('has_completed', has_completed),
                                   ('finish_time', row.ft),
                                   ('percent_complete', row.percent_complete),
                                   ('n_tasks', row.n_tasks),
                                   ('pending_tasks', row.pending_tasks),
                                   ('n_workers', row.n_workers),
                                   ('n_answers', row.n_answers),
                                   ('workers', row.workers),
                                   ('updated', row.updated),
                                   ('oldest_available', row.oldest_available),
                                   ('last_submission', row.last_submission),
                                   ('n_taskruns', row.n_taskruns),
                                   ('pending_taskruns', row.pending_taskruns)])

            projects.append(project)
        return pd.DataFrame(projects)
コード例 #36
0
def user_progress(project_id=None, short_name=None):
    """API endpoint for user progress.

    Return a JSON object with four fields regarding the tasks for the user:
        { 'done': 10,
          'total: 100,
          'remaining': 90,
          'remaining_for_user': 45
        }
       This will mean that the user has done 10% of the available tasks for the
       project, 90 tasks are yet to be submitted and the user can access 45 of
       them based on user preferences.

    """
    if current_user.is_anonymous:
        return abort(401)
    if project_id or short_name:
        if short_name:
            project = project_repo.get_by_shortname(short_name)
        elif project_id:
            project = project_repo.get(project_id)

        if project:
            # For now, keep this version, but wait until redis cache is
            # used here for task_runs too
            query_attrs = dict(project_id=project.id)
            query_attrs['user_id'] = current_user.id
            taskrun_count = task_repo.count_task_runs_with(**query_attrs)
            num_available_tasks = n_available_tasks(project.id,
                                                    current_user.id)
            num_available_tasks_for_user = n_available_tasks_for_user(
                project, current_user.id)
            response = dict(done=taskrun_count,
                            total=n_tasks(project.id),
                            remaining=num_available_tasks,
                            remaining_for_user=num_available_tasks_for_user,
                            quiz=current_user.get_quiz_for_project(project))
            return Response(json.dumps(response), mimetype="application/json")
        else:
            return abort(404)
    else:  # pragma: no cover
        return abort(404)
コード例 #37
0
    def get_projects_report(self, base_url):
        sql = text(
            '''WITH completed_tasks AS 
              (
                 SELECT
                    task.project_id,
                    COUNT(DISTINCT task.id) AS value,
                    MAX(task_run.finish_time) AS ft 
                 FROM task INNER JOIN task_run on task.id = task_run.task_id 
                 WHERE task.state = 'completed' 
                 GROUP BY task.project_id 
              ), all_tasks AS 
              (
                 SELECT
                    project_id,
                    COUNT(task.id) AS value 
                 FROM task 
                 GROUP BY project_id 
              ), workers AS 
              (
                 SELECT DISTINCT
                    project_id,
                    user_id,
                    public.user.fullname,
                    public.user.email_addr 
                 FROM task_run INNER JOIN public.user ON task_run.user_id = public.user.id 
              ), n_workers AS 
              (
                 SELECT
                    project_id,
                    COUNT(user_id) as value 
                 FROM workers 
                 GROUP BY project_id 
              )
              SELECT
                 project.id,
                 project.name,
                 project.short_name,
                 project.description,
                 project.long_description,
                 project.created,
                 u.name as owner_name,
                 u.email_addr as owner_email,
                 category.name as category_name,
                 project.allow_anonymous_contributors,
                 (
                    COALESCE(project.info::json ->> 'passwd_hash', 'null') != 'null' 
                 )
                 as password_protected,
                 project.webhook,
                 COALESCE(project.info::json ->> 'sched', 'default') as scheduler,
                 completed_tasks.ft,
                 CASE
                    WHEN
                       all_tasks.value = 0 
                       OR completed_tasks.value IS NULL 
                    THEN
                       0 
                    ELSE
                       completed_tasks.value * 100 / all_tasks.value 
                 END
                 as percent_complete, COALESCE(all_tasks.value, 0) AS n_tasks, COALESCE(all_tasks.value, 0) - COALESCE(completed_tasks.value, 0) AS pending_tasks, COALESCE(n_workers.value, 0) as n_workers, 
                 (
                    SELECT
                       n_answers 
                    FROM
                       task 
                    WHERE
                       project_id = project.id 
                    ORDER BY
                       task.id DESC LIMIT 1
                 )
                 as n_answers,
                 (
                    SELECT
                       string_agg(concat('(', workers.user_id, ';', workers.fullname, ';', workers.email_addr, ')'), '|')
                    FROM
                       workers 
                    WHERE
                       project.id = workers.project_id 
                 )
                 as workers 
              FROM
                 project 
                 INNER JOIN
                    public.user as u 
                    on project.owner_id = u.id 
                 INNER JOIN
                    category 
                    on project.category_id = category.id 
                 LEFT OUTER JOIN
                    completed_tasks 
                    ON project.id = completed_tasks.project_id 
                 LEFT OUTER JOIN
                    all_tasks 
                    ON project.id = all_tasks.project_id 
                 LEFT OUTER JOIN
                    n_workers 
                    ON project.id = n_workers.project_id;''')

        results = self.db.session.execute(sql)
        projects = []

        for row in results:
            coowners = self.get_by_shortname(row.short_name).coowners
            num_available_tasks = n_available_tasks(row.id)
            has_completed = "False"
            coowner_names = "None"
            if coowners:
                coowner_names = ""
                for co in coowners:
                    coowner_names += co.name + ";" + co.email_addr + "| "
            if num_available_tasks == 0:
                has_completed = "True"
            project = AttrDict([('id', row.id),
              ('name', row.name),
              ('short_name', row.short_name),
              ('url', base_url + row.short_name),
              ('description', row.description),
              ('long_description', row.long_description),
              ('created', row.created),
              ('owner_name', row.owner_name),
              ('owner_email', row.owner_email),
              ('coowners', coowner_names),
              ('category_name', row.category_name),
              ('allow_anonymous_contributors', row.allow_anonymous_contributors),
              ('password_protected', row.password_protected),
              ('webhook', row.webhook),
              ('scheduler', row.scheduler),
              ('has_completed', has_completed),
              ('finish_time', row.ft),
              ('percent_complete', row.percent_complete),
              ('n_tasks', row.n_tasks),
              ('pending_tasks', row.pending_tasks),
              ('n_workers', row.n_workers), 
              ('n_answers', row.n_answers),
              ('workers', row.workers)
              ])

            projects.append(project)
        return projects