def _test_get_breadth_first_task(self, user=None, external_uid=None): self.del_task_runs() if user: short_name = 'xyzuser' else: short_name = 'xyznouser' category = db.session.query(Category).get(1) project = Project(short_name=short_name, name=short_name, description=short_name, category=category) owner = db.session.query(User).get(1) project.owner = owner task = Task(project=project, state='0', info={}) task2 = Task(project=project, state='0', info={}) task.project = project task2.project = project db.session.add(project) db.session.add(task) db.session.add(task2) db.session.commit() taskid = task.id projectid = project.id # give task2 a bunch of runs for idx in range(2): self._add_task_run(project, task2) # now check we get task without task runs as anonymous user out = pybossa.sched.get_breadth_first_task(projectid) assert out.id == taskid, out # now check we get task without task runs as a user owner = db.session.query(User).get(1) out = pybossa.sched.get_breadth_first_task(projectid, owner.id) assert out.id == taskid, out # now check we get task without task runs as a external uid out = pybossa.sched.get_breadth_first_task(projectid, external_uid=external_uid) assert out.id == taskid, out # now check that offset works out1 = pybossa.sched.get_breadth_first_task(projectid) out2 = pybossa.sched.get_breadth_first_task(projectid, offset=1) assert out1.id != out2.id, out # asking for a bigger offset (max 10) out2 = pybossa.sched.get_breadth_first_task(projectid, offset=11) assert out2 is None, out self._add_task_run(project, task) out = pybossa.sched.get_breadth_first_task(projectid) assert out.id == taskid, out # now add 2 more taskruns. We now have 3 and 2 task runs per task self._add_task_run(project, task) self._add_task_run(project, task) out = pybossa.sched.get_breadth_first_task(projectid) assert out.id == task2.id, out
def public_published_projects(user_id): """Return projects that user_id has contributed to. Public information only""" unsanitized_projects = published_projects(user_id) public_projects = [] if unsanitized_projects: p = Project() for project in unsanitized_projects: public_project = p.to_public_json(data=project) public_projects.append(public_project) return public_projects
def _filter_private_data(self, data): tmp = copy.deepcopy(data) public = Project().public_attributes() public.append('link') public.append('links') for key in tmp.keys(): if key not in public: del tmp[key] for key in tmp['info'].keys(): if key not in Project().public_info_keys(): del tmp['info'][key] return tmp
def test_all(self): """Test MODEL works""" username = u'test-user-1' user = User(name=username, fullname=username, email_addr=username) info = { 'total': 150, 'long_description': 'hello world'} project = Project( name=u'My New Project', short_name=u'my-new-app', description=u'description', info=info) category = Category(name=u'cat', short_name=u'cat', description=u'cat') project.category = category project.owner = user task_info = { 'question': 'My random question', 'url': 'my url'} task = Task(info=task_info) task_run_info = {'answer': u'annakarenina'} task_run = TaskRun(info=task_run_info) task.project = project task_run.task = task task_run.project = project task_run.user = user db.session.add_all([user, project, task, task_run]) db.session.commit() project_id = project.id db.session.remove() project = db.session.query(Project).get(project_id) assert project.name == u'My New Project', project # year would start with 201... assert project.created.startswith('201'), project.created assert project.long_tasks == 0, project.long_tasks assert project.hidden == 0, project.hidden assert project.time_estimate == 0, project assert project.time_limit == 0, project assert project.calibration_frac == 0, project assert project.bolt_course_id == 0 assert len(project.tasks) == 1, project assert project.owner.name == username, project out_task = project.tasks[0] assert out_task.info['question'] == task_info['question'], out_task assert out_task.quorum == 0, out_task assert out_task.state == "ongoing", out_task assert out_task.calibration == 0, out_task assert out_task.priority_0 == 0, out_task assert len(out_task.task_runs) == 1, out_task outrun = out_task.task_runs[0] assert outrun.info['answer'] == task_run_info['answer'], outrun assert outrun.user.name == username, outrun
def test_all(self): """Test MODEL works""" username = u'test-user-1' user = User(name=username, fullname=username, email_addr=username) info = {'total': 150, 'long_description': 'hello world'} project = Project(name=u'My New Project', short_name=u'my-new-app', description=u'description', info=info) category = Category(name=u'cat', short_name=u'cat', description=u'cat') project.category = category project.owner = user task_info = {'question': 'My random question', 'url': 'my url'} task = Task(info=task_info) task_run_info = {'answer': u'annakarenina'} task_run = TaskRun(info=task_run_info) task.project = project task_run.task = task task_run.project = project task_run.user = user db.session.add_all([user, project, task, task_run]) db.session.commit() project_id = project.id db.session.remove() project = db.session.query(Project).get(project_id) assert project.name == u'My New Project', project # year would start with 20... - 2020 is coming assert project.created.startswith('20'), project.created assert len(project.tasks) == 1, project assert project.owner.name == username, project out_task = project.tasks[0] assert out_task.info['question'] == task_info['question'], out_task assert out_task.quorum == 0, out_task assert out_task.state == "completed", out_task assert out_task.calibration == 0, out_task assert out_task.priority_0 == 0, out_task assert len(out_task.task_runs) == 1, out_task outrun = out_task.task_runs[0] assert outrun.info['answer'] == task_run_info['answer'], outrun assert outrun.user.name == username, outrun
def create_project(cls, info): category = db.session.query(Category).first() if category is None: cls.create_categories() category = db.session.query(Category).first() project = Project(name=cls.project_name, short_name=cls.project_short_name, description=u'description', hidden=0, category_id=category.id, info=info) return project
def _preprocess_post_data(self, data): project_id = data["project_id"] info = data["info"] duplicate = task_repo.find_duplicate(project_id=project_id, info=info) if duplicate: message = {'reason': 'DUPLICATE_TASK', 'task_id': duplicate} raise Conflict(json.dumps(message)) if 'n_answers' not in data: project = Project(**get_project_data(project_id)) data['n_answers'] = project.get_default_n_answers() invalid_fields = validate_required_fields(info) if invalid_fields: raise BadRequest('Missing or incorrect required fields: {}'.format( ','.join(invalid_fields))) if data.get('gold_answers'): try: gold_answers = data['gold_answers'] if type(gold_answers) is dict: data['calibration'] = 1 data['exported'] = True except Exception as e: raise BadRequest('Invalid gold_answers')
def setUp(self): super(TestBlogpostModel, self).setUp() with self.flask_app.app_context(): user = User(email_addr="*****@*****.**", name="johndoe", fullname="John Doe", locale="en") category = Category(name=u'cat', short_name=u'cat', description=u'cat') project = Project(name='Application', short_name='app', description='desc', owner=user, category=category) db.session.add(user) db.session.add(project) db.session.commit()
def create_project(self, info): with self.flask_app.app_context(): category = db.session.query(Category).first() if category is None: self._create_categories() category = db.session.query(Category).first() project = Project(name=self.project_name, short_name=self.project_short_name, description=u'description', hidden=0, category_id=category.id, info=info) return project
def add_task_event(mapper, conn, target): """Update PYBOSSA feed with new task.""" sql_query = ('select name, short_name, info from project \ where id=%s') % target.project_id results = conn.execute(sql_query) obj = dict(action_updated='Task') tmp = dict() for r in results: tmp['id'] = target.project_id tmp['name'] = r.name tmp['short_name'] = r.short_name tmp['info'] = r.info tmp = Project().to_public_json(tmp) obj.update(tmp) update_feed(obj)
def add_project_event(mapper, conn, target): """Update PYBOSSA feed with new project.""" tmp = dict(id=target.id, name=target.name, short_name=target.short_name, info=target.info) obj = dict(action_updated='Project') tmp = Project().to_public_json(tmp) obj.update(tmp) update_feed(obj) # Create a clean projectstats object for it sql_query = """INSERT INTO project_stats (project_id, n_tasks, n_task_runs, n_results, n_volunteers, n_completed_tasks, overall_progress, average_time, n_blogposts, last_activity, info) VALUES (%s, 0, 0, 0, 0, 0, 0, 0, 0, 0, '{}');""" % (target.id) conn.execute(sql_query)
def on_taskrun_submit(mapper, conn, target): """Update the task.state when n_answers condition is met.""" # Get project details sql_query = ( 'select name, short_name, published, webhook, info, category_id \ from project where id=%s') % target.project_id results = conn.execute(sql_query) tmp = dict() for r in results: tmp['name'] = r.name tmp['short_name'] = r.short_name _published = r.published tmp['info'] = r.info _webhook = r.webhook tmp['category_id'] = r.category_id tmp['id'] = target.project_id project_public = dict() project_public.update(Project().to_public_json(tmp)) project_public['action_updated'] = 'TaskCompleted' sched.after_save(target, conn) add_user_contributed_to_feed(conn, target.user_id, project_public) # golden tasks never complete; bypass update to task.state # mark task as exported false for each task run submissions task = task_repo.get_task(id=target.task_id) if task.calibration: if task.exported and _published: sql_query = ("""UPDATE task SET exported=False \ WHERE id=%s;""") % (task.id) conn.execute(sql_query) return is_completed = is_task_completed(conn, target.task_id, target.project_id) if is_completed: update_task_state(conn, target.task_id) check_and_send_task_notifications(target.project_id, conn) if is_completed and _published: update_feed(project_public) result_id = create_result(conn, target.project_id, target.task_id) project_private = dict() project_private.update(project_public) project_private['webhook'] = _webhook push_webhook(project_private, target.task_id, result_id)
def add_blog_event(mapper, conn, target): """Update PYBOSSA feed with new blog post.""" sql_query = ('select name, short_name, info from project \ where id=%s') % target.project_id results = conn.execute(sql_query) obj = dict(action_updated='Blog') tmp = dict() for r in results: tmp['id'] = target.project_id tmp['name'] = r.name tmp['short_name'] = r.short_name tmp['info'] = r.info tmp = Project().to_public_json(tmp) obj.update(tmp) update_feed(obj) # Notify volunteers mail_queue.enqueue(notify_blog_users, blog_id=target.id, project_id=target.project_id)
def handle_valid_project_form(form, template, volume, category): """Handle a valid project form.""" import_data = volume.get('data', {}) import_data['type'] = volume.get('importer') # Use enhanced IIIF importer for IIIF projects if import_data['type'] == 'iiif': import_data['type'] = 'iiif-enhanced' # Check for parent if template['parent_template_id']: if volume.get('importer') != 'iiif': flash('Only IIIF projects can be built from parents.', 'error') return parent = get_parent(template['parent_template_id'], volume['id'], category) if not parent: msg = 'There is no valid parent for this template and volume.' flash(msg, 'error') return import_data['parent_id'] = parent.id # Create project webhook = '{0}lc/analysis'.format(request.url_root) project = Project(name=form.name.data, short_name=form.short_name.data, description=template['description'], long_description='', owner_id=current_user.id, info={ 'volume_id': volume['id'], 'template_id': template['id'] }, webhook=webhook, published=True, category_id=category.id, owners_ids=[current_user.id]) add_avatar_to_project_info(project, volume) project_repo.save(project) return generate_tasks(project, import_data, template)
def add_blog_event(mapper, conn, target): """Update PYBOSSA feed with new blog post.""" sql_query = ('select name, short_name, info from project \ where id=%s') % target.project_id results = conn.execute(sql_query) obj = dict(action_updated='Blog') tmp = dict() for r in results: tmp['id'] = target.project_id tmp['name'] = r.name tmp['short_name'] = r.short_name tmp['info'] = r.info tmp = Project().to_public_json(tmp) obj.update(tmp) update_feed(obj) # Notify volunteers if current_app.config.get('DISABLE_EMAIL_NOTIFICATIONS') is None: scheme = current_app.config.get('PREFERRED_URL_SCHEME', 'http') mail_queue.enqueue(notify_blog_users, blog_id=target.id, project_id=target.project_id) contents = {"en": "New update!"} headings = {"en": target.title} launch_url = url_for('project.show_blogpost', short_name=tmp['short_name'], id=target.id, _scheme=scheme, _external=True) # print launch_url web_buttons = [{ "id": "read-more-button", "text": "Read more", "icon": "http://i.imgur.com/MIxJp1L.png", "url": launch_url }] webpush_queue.enqueue(push_notification, project_id=target.project_id, contents=contents, headings=headings, web_buttons=web_buttons, launch_url=launch_url)
def get_top(n=4): """Return top n=4 projects.""" sql = text('''SELECT project.id, project.name, project.short_name, project.description, project.info, COUNT(project_id) AS total FROM task_run, project WHERE project_id IS NOT NULL AND project.id=project_id AND (project.info->>'passwd_hash') IS NULL GROUP BY project.id ORDER BY total DESC LIMIT :limit;''') results = session.execute(sql, dict(limit=n)) top_projects = [] for row in results: project = dict(id=row.id, name=row.name, short_name=row.short_name, description=row.description, info=row.info, n_volunteers=n_volunteers(row.id), n_completed_tasks=n_completed_tasks(row.id)) top_projects.append(Project().to_public_json(project)) return top_projects
def test_task_errors(self): """Test TASK model errors.""" user = User(email_addr="*****@*****.**", name="johndoe", fullname="John Doe", locale="en") db.session.add(user) db.session.commit() user = db.session.query(User).first() category = Category(name=u'cat', short_name=u'cat', description=u'cat') project = Project(name='Application', short_name='app', description='desc', owner_id=user.id, category=category) db.session.add(project) db.session.commit() task = Task(project_id=None) db.session.add(task) assert_raises(IntegrityError, db.session.commit) db.session.rollback()
def test_03_package_create(self, Mock): """Test CKAN package_create works""" # It should return self.pkg_json_found with an empty Resources list html_request = FakeRequest(json.dumps(self.pkg_json_found), 200, {'content-type': 'application/json'}) Mock.return_value = html_request with self.flask_app.test_request_context('/'): # Resource that exists project = Project(short_name='urbanpark', name='Urban Parks') user = User(fullname='Daniel Lombrana Gonzalez') out = self.ckan.package_create(project=project, user=user, url="http://something.com") err_msg = "The package ID should be the same" assert out['id'] == self.package_id, err_msg # Check the exception Mock.return_value = self.server_error try: self.ckan.package_create(project=project, user=user, url="http://something.com") except Exception as out: type, msg, status_code = out.args assert "Server Error" in msg, msg assert 500 == status_code, status_code assert "CKAN: the remote site failed! package_create failed" == type, type
def on_taskrun_submit(mapper, conn, target): """Update the task.state when n_answers condition is met.""" # Get project details sql_query = ( 'select name, short_name, published, webhook, info, category_id \ from project where id=%s') % target.project_id results = conn.execute(sql_query) tmp = dict() for r in results: tmp['name'] = r.name tmp['short_name'] = r.short_name _published = r.published tmp['info'] = r.info _webhook = r.webhook tmp['category_id'] = r.category_id tmp['id'] = target.project_id project_public = dict() project_public.update(Project().to_public_json(tmp)) project_public['action_updated'] = 'TaskCompleted' sched.after_save(target, conn) add_user_contributed_to_feed(conn, target.user_id, project_public) if is_task_completed(conn, target.task_id, target.project_id): update_task_state(conn, target.task_id) update_feed(project_public) result_id = create_result(conn, target.project_id, target.task_id) project_private = dict() project_private.update(project_public) project_private['webhook'] = _webhook push_webhook(project_private, target.task_id, result_id) # Every time a registered user contributes a taskrun its notified_at column is reset # so the job for deleting inactive accounts, is not triggered if target.user_id: sql = f"update \"user\" set notified_at=null where \"user\".id={target.user_id};" conn.execute(sql)
def text_search(search_text, show_unpublished=True, show_hidden=True): """Return a list of published projects short_names. """ sql = text('''SELECT project.id, project.name, project.short_name, project.description, project.info, project.created, project.updated, project.category_id, project.featured, "user".fullname AS owner FROM project LEFT JOIN "user" ON project.owner_id="user".id WHERE (project.name ILIKE '%' || :search_text || '%' OR "user".fullname ILIKE '%' || :search_text || '%' OR project.description ILIKE '%' || :search_text || '%') {} {} ORDER BY project.name;'''.format( 'AND project.published=true' if not show_unpublished else '', 'AND coalesce(project.hidden, false)=false' if not show_hidden else '')) results = session.execute(sql, dict(search_text=search_text)) projects = [] for row in results: project = dict(id=row.id, name=row.name, short_name=row.short_name, created=row.created, updated=row.updated, description=row.description, owner=row.owner, featured=row.featured, last_activity=pretty_date(last_activity(row.id)), last_activity_raw=last_activity(row.id), overall_progress=overall_progress(row.id), n_tasks=n_tasks(row.id), n_volunteers=n_volunteers(row.id), info=row.info) projects.append(Project().to_public_json(project)) return projects
def test_info_public_keys_extension(self): """Test DomainObject to_public_json method works with extra fields.""" project = Project() project.name = 'test' project.short_name = 'test' project.description = 'Desc' project.info = dict(container='3', thumbnail='img.png', token='secret', tutorial='help', sched='default', task_presenter='something', super_secret='hidden', public_field='so true') project_dict = project.dictize() json = project.to_public_json() err_msg = "Wrong value" assert json['name'] == project.name, err_msg err_msg = "Missing fields" assert json.keys().sort() == project.public_attributes().sort( ), err_msg err_msg = "There should be info keys" assert json['info'].keys().sort() == Project().public_info_keys().sort( ), err_msg with patch.dict(self.flask_app.config, {'PROJECT_INFO_PUBLIC_FIELDS': ['public_field']}): json = project.to_public_json() assert json['info'].keys().sort() == Project().public_info_keys( ).sort(), err_msg assert 'public_field' in json['info'].keys() assert 'secret_key' not in json['info'].keys()
def test_project_errors(self): """Test project model errors.""" project = Project(name='Project', short_name='proj', description='desc', owner_id=None) # Project.owner_id should not be nullable db.session.add(project) assert_raises(IntegrityError, db.session.commit) db.session.rollback() # Project.name should not be nullable user = User(email_addr="*****@*****.**", name="johndoe", fullname="John Doe", locale="en") db.session.add(user) db.session.commit() user = db.session.query(User).first() project.owner_id = user.id project.name = None db.session.add(project) assert_raises(IntegrityError, db.session.commit) db.session.rollback() project.name = '' db.session.add(project) assert_raises(IntegrityError, db.session.commit) db.session.rollback() # Project.short_name should not be nullable project.name = "Project" project.short_name = None db.session.add(project) assert_raises(IntegrityError, db.session.commit) db.session.rollback() project.short_name = '' db.session.add(project) assert_raises(IntegrityError, db.session.commit) db.session.rollback() # Project.description should not be nullable db.session.add(project) project.short_name = "project" project.description = None assert_raises(IntegrityError, db.session.commit) db.session.rollback() project.description = '' db.session.add(project) assert_raises(IntegrityError, db.session.commit) db.session.rollback() # Project.featured should not be nullable project.description = 'description' project.featured = None db.session.add(project) assert_raises(IntegrityError, db.session.commit) db.session.rollback()
def update_audit_data(mapper, conn, target): try: if not isinstance(target.info, dict): return data = target.info if not data.has_key('result'): return sql_query = ( 'select id from project where category_id in (select category_id \ from project where id=%s) and id != %s') % (target.project_id, target.project_id) print(sql_query) result = conn.execute(sql_query) print(3432432) one = result.fetchone() if len(one) <= 0: return project_id = one[0] print(one) info = {} print(target.__dict__) info['project_id'] = project_id info['task_id'] = target.task_id info['user_id'] = target.user_id info['user_ip'] = "" info['finish_time'] = target.finish_time info['result'] = data['result'] info['answers'] = data['answers'] info['question'] = data['question'] info['link'] = data['link'] info['url_m'] = data['url_m'] info['url_b'] = data['url_b'] sql_query = ( "insert into task(created, project_id, state, quorum, calibration, \ priority_0, info, n_answers) values (TIMESTAMP '%s', %s, 'ongoing', 0, 0, 0, '%s', 30) RETURNING id;" % (make_timestamp(), project_id, json.dumps(info))) print(sql_query) result = conn.execute(sql_query) id_of_new_row = result.fetchone()[0] print(id_of_new_row) sql_query = ( "insert into counter(created, project_id, task_id, n_task_runs) \ VALUES (TIMESTAMP '%s', %s, %s, 0)" % (make_timestamp(), project_id, id_of_new_row)) print(sql_query) conn.execute(sql_query) print(sql_query) """Update PYBOSSA feed with new task.""" sql_query = ('select name, short_name, info from project \ where id=%s') % project_id results = conn.execute(sql_query) obj = dict(action_updated='Task') tmp = dict() for r in results: tmp['id'] = project_id tmp['name'] = r.name tmp['short_name'] = r.short_name tmp['info'] = r.info tmp = Project().to_public_json(tmp) obj.update(tmp) update_feed(obj) except: raise