def test_project_meta_dict(self): project_name = "project3" owner_id = "testuser" summary = "a summary" product = "fire" project = CodeDoubanProject.add(project_name, owner_id, summary, product) # hookfile_path = "%s/hooks/post-receive" % project.git_real_path project = CodeDoubanProject.get_by_name(project_name) data = { 'url': "%s/%s" % (DOMAIN, project_name), 'name': project_name, 'description': summary, 'product': product, 'committers_count': 0, 'forked_count': 0, 'open_issues_count': 0, 'open_tickets_count': 0, 'watched_count': 0, 'owner': { 'name': owner_id, 'avatar': gravatar_url(owner_id + '@douban.com'), }, } commits = project.git.get_revisions("HEAD~1", "HEAD") if commits: data['last_commit'] = commits[0] ok_(project.get_info() == data) project.delete()
def _q_index(request): user = request.user my_issues = [] if user: username = user.username your_projects = CodeDoubanProject.get_projects(owner=username, sortby='lru') watched_projects = CodeDoubanProject.get_watched_others_projects_by_user( # noqa user=username, sortby='lru') teams = Team.get_by_user_id(user.name) actions = get_user_inbox(username).get_actions( stop=PAGE_ACTIONS_COUNT - 1) badge_items = user.get_badge_items() # pull request # your_tickets = user.get_user_pull_requests_rank(limit=5) your_tickets = user.get_user_submit_pull_requests(limit=5) # issue project_ids = CodeDoubanProject.get_ids(user.name) dt = { 'state': "open", 'limit': 5, 'start': 0, } my_issues = ProjectIssue.gets_by_project_ids(project_ids, **dt) return st('newsfeed.html', **locals()) return request.redirect("/teams/")
def get_temp_project(origin=None, repo_path=BARE_REPO_PATH): if origin: prefix_path = get_repo_root() temp_repo_path = tempfile.mkdtemp(suffix=".git", prefix="test_", dir=prefix_path) project_name = temp_repo_path[len(prefix_path) + 1:][:-4] project = CodeDoubanProject.add(project_name, TEMP_PROJECT_OWNER, TEMP_PROJECT_DESCRIPTION, fork_from=origin.id, create_trac=False) return project prefix_path = get_repo_root() temp_repo_path = tempfile.mkdtemp(suffix=".git", prefix="test_", dir=prefix_path) project_name = temp_repo_path[len(prefix_path) + 1:][:-4] project = CodeDoubanProject.add(project_name, TEMP_PROJECT_OWNER, TEMP_PROJECT_DESCRIPTION) shutil.rmtree(temp_repo_path) repo = Jagare(repo_path) repo.clone(temp_repo_path, bare=True) return project
def test_create_git_repo(self): git_path = os.path.join(get_repo_root(), "abc.git") CodeDoubanProject.create_git_repo(git_path) assert os.path.exists(git_path) info_file = os.path.join(git_path, "refs") assert os.path.exists(info_file) shutil.rmtree(git_path)
def test_create_git_repo(self): git_path = os.path.join(get_repo_root(), 'abc.git') CodeDoubanProject.create_git_repo(git_path) assert os.path.exists(git_path) info_file = os.path.join(git_path, 'refs') assert os.path.exists(info_file) shutil.rmtree(git_path)
def create(self, request): user = request.user if not user: raise AccessError from_proj = request.get_form_var('from_proj') from_ref = request.get_form_var('from_ref') to_ref = request.get_form_var('to_ref') to_proj = request.get_form_var('to_proj') title = request.get_form_var('title', '').decode('utf-8') comment = request.get_form_var('body', '').decode('utf-8') if not all([from_ref, from_proj, to_ref, to_proj]): raise TraversalError from_proj = CodeDoubanProject.get_by_name(from_proj) to_proj = CodeDoubanProject.get_by_name(to_proj) if from_proj != to_proj: if not from_proj.has_push_perm(user.name): raise AccessError( "Need push permission to create PR on another project") pullreq = PullRequest.open(from_proj, from_ref, to_proj, to_ref) ticket = Ticket(None, None, to_proj.id, title, comment, user.username, None, None) pullreq = add_pull(ticket, pullreq, user) ticket = pullreq.ticket return request.redirect( str('/%s/pull/%s/' % (to_proj.name, ticket.ticket_id)))
def test_multiple_project_index(self): skip_test() for i in range(5): CodeDoubanProject.add('test%s' % i, 'owner', create_trac=False) _reposearch.RepoSearch.index_repos() objs = _reposearch.RepoSearch.query_repo_objs() assert len(objs) == 5
def create(self, request): user = request.user if not user: raise AccessError from_proj = request.get_form_var('from_proj') from_ref = request.get_form_var('from_ref') to_ref = request.get_form_var('to_ref') to_proj = request.get_form_var('to_proj') title = request.get_form_var('title', '').decode('utf-8') comment = request.get_form_var('body', '').decode('utf-8') if not all([from_ref, from_proj, to_ref, to_proj]): raise TraversalError from_proj = CodeDoubanProject.get_by_name(from_proj) to_proj = CodeDoubanProject.get_by_name(to_proj) if from_proj != to_proj: if not from_proj.has_push_perm(user.name): raise AccessError( "Need push permission to create PR on another project") pullreq = PullRequest.open(from_proj, from_ref, to_proj, to_ref) ticket = Ticket(None, None, to_proj.id, title, comment, user.username, None, None) pullreq = add_pull(ticket, pullreq, user) ticket = pullreq.ticket return request.redirect(str('/%s/pull/%s/' % (to_proj.name, ticket.ticket_id)))
def test_project_meta_dict(self): project_name = "project3" owner_id = "testuser" summary = "a summary" product = "fire" project = CodeDoubanProject.add( project_name, owner_id, summary, product) # hookfile_path = "%s/hooks/post-receive" % project.git_real_path project = CodeDoubanProject.get_by_name(project_name) data = { 'url': "%s/%s" % (DOMAIN, project_name), 'name': project_name, 'description': summary, 'product': product, 'committers_count': 0, 'forked_count': 0, 'open_issues_count': 0, 'open_tickets_count': 0, 'watched_count': 0, 'owner': { 'name': owner_id, 'avatar': gravatar_url(owner_id + '@douban.com'), }, } commits = project.git.get_revisions("HEAD~1", "HEAD") if commits: data['last_commit'] = commits[0] ok_(project.get_info() == data) project.delete()
def test_multiple_project_index(self): skip_test() for i in range(5): CodeDoubanProject.add( 'test%s' % i, 'owner%s' % i, create_trac=False) _usersearch.UserSearch.index_users() objs = _usersearch.UserSearch.query_user_objs() assert len(objs) == 5
def test_multiple_project_index(self): skip_test() for i in range(5): CodeDoubanProject.add('test%s' % i, 'owner%s' % i, create_trac=False) _usersearch.UserSearch.index_users() objs = _usersearch.UserSearch.query_user_objs() assert len(objs) == 5
def test_destroy_hook(self): url = "http://this.is.other.url" prj = self._prj() hook = CodeDoubanHook.add(url, prj.id) hooked_project = CodeDoubanProject.get(hook.project_id) assert len(hooked_project.hooks) == 1 hooked_project = CodeDoubanProject.get(hook.project_id) hook.destroy() assert len(hooked_project.hooks) == 0
def test_get_forked_from_should_return_origin_project(self): prj = CodeDoubanProject.get_by_name('orig') prj.delete() prj = CodeDoubanProject.get_by_name('fork') prj.delete() orig = CodeDoubanProject.add('orig', owner_id="test1") fork = orig.fork('fork', 'user2') source = fork.get_forked_from() eq_(source, orig)
def test_project_validate(self): noname_project = CodeDoubanProject( 108, '', "test1", "testuser", datetime.now(), "fire", '/fake_path', '/fake_path') ok_project = CodeDoubanProject( 108, 'project6', "testuser", datetime.now(), "test", "fire", '/fake_path', '/fake_path') ok_(bool(noname_project.validate())) ok_(not bool(ok_project.validate()))
def test_create(self): git_path = os.path.join(get_repo_root(), 'test_create.git') assert not os.path.exists( git_path), "git_path should not exist prior repo creation" CodeDoubanProject.create_git_repo(git_path) assert os.path.exists( git_path), "create_git_repo should create git_path" refs_file = os.path.join(git_path, 'refs') assert os.path.exists(refs_file), \ "create_git_repo should create a git repo with refs subdir"
def _repo(self, name, bare=True): git_path = self._path(name) if bare: work_tree_path = None else: work_tree_path = self._path_work_tree(name) os.mkdir(work_tree_path) CodeDoubanProject.create_git_repo(git_path) repo = git.GitRepo(git_path, work_tree=work_tree_path) return repo
def yours(request): user = request.user actions = (get_user_feed( user.username).get_actions(stop=PAGE_ACTIONS_COUNT - 1)) your_projects = CodeDoubanProject.get_projects(owner=user.username, sortby="lru") watched_projects = CodeDoubanProject.get_watched_others_projects_by_user( user=user.username, sortby='lru') badge_items = user.get_badge_items() return st('my_actions.html', **locals())
def yours(request): user = request.user actions = (get_user_feed(user.username) .get_actions(stop=PAGE_ACTIONS_COUNT - 1)) your_projects = CodeDoubanProject.get_projects( owner=user.username, sortby="lru") watched_projects = CodeDoubanProject.get_watched_others_projects_by_user( user=user.username, sortby='lru') badge_items = user.get_badge_items() return st('my_actions.html', **locals())
def update_repo_indexes(cls): old_obj_ids = cls.query_repo_objs() old_obj_ids = [id for id, in old_obj_ids] new_obj_ids = CodeDoubanProject.get_project_ids_sortby_sumup() new_objs = CodeDoubanProject.gets(new_obj_ids) to_delete_ids = set(old_obj_ids) - set(new_obj_ids) cls.delete_repo_indexes(to_delete_ids) index_data = [cls.get_repo_index_from_project(project) for project in new_objs] indexes = [(data['id'], data) for data in index_data] IndexEngine.create_index_bulk('repo', indexes)
def add_fork_project(project): name = "%s/%s" % (project.owner_id, project.name) _project = CodeDoubanProject.add( name=name, owner_id=project.owner_id, summary=project.summary, product=project.product, fork_from=project.fork_from, intern_banned=project.intern_banned) if _project: fork_from_project = CodeDoubanProject.get(project.fork_from) _project.update(project.summary, project.product, name, fork_from_project.intern_banned) return _project
def _repo(self, name, bare=True): git_path = self._path(name) if bare: work_tree_path = None else: work_tree_path = self._path_work_tree(name) os.mkdir(work_tree_path) try: CodeDoubanProject.create_git_repo(git_path) except: pass repo = git.GitRepo(git_path, work_tree=work_tree_path) return repo
def test_get_fork_network_should_return_all_projects_with_same_origin(self): # noqa prj = CodeDoubanProject.get_by_name('orig') prj.delete() orig = CodeDoubanProject.add('orig', owner_id="test1") fork = orig.fork('fork1', 'user1') fork2 = orig.fork('fork2', 'user2') fork3 = fork.fork('fork3', 'user3') expected_network = set([orig, fork, fork2, fork3]) for proj in [orig, fork, fork2, fork3]: network = proj.get_fork_network() eq_(set(network), expected_network)
def test_update_can_push(self): project_name = "project11" owner_id = "testuser" summary = "a summary" product = "fire" CodeDoubanProject.add(project_name, owner_id, summary, product) p = CodeDoubanProject.get_by_name('project11') assert p.can_push == 1 p.update_can_push(False) p = CodeDoubanProject.get_by_name('project11') assert p.can_push == 0 p.update_can_push(True) p = CodeDoubanProject.get_by_name('project11') assert p.can_push == 1
def update_repo_indexes(cls): old_obj_ids = cls.query_repo_objs() old_obj_ids = [id for id, in old_obj_ids] new_obj_ids = CodeDoubanProject.get_project_ids_sortby_sumup() new_objs = CodeDoubanProject.gets(new_obj_ids) to_delete_ids = set(old_obj_ids) - set(new_obj_ids) cls.delete_repo_indexes(to_delete_ids) index_data = [ cls.get_repo_index_from_project(project) for project in new_objs ] indexes = [(data['id'], data) for data in index_data] IndexEngine.create_index_bulk('repo', indexes)
def test_transfer_project(self): pname1 = 'project6' pname2 = 'project7' proj_owner = 'admin_user' to_user = '******' p = CodeDoubanProject.add(pname1, owner_id=proj_owner, summary="test", product="fire") _ = CodeDoubanProject.add(pname2, owner_id=proj_owner, summary="test", product="fire") p.transfer_to(to_user) p1 = CodeDoubanProject.get_by_name(pname1) assert p1.owner_id == to_user p2 = CodeDoubanProject.get_by_name(pname2) assert p2.owner_id == proj_owner
def _repo(self, name, bare=True): git_path = self._path(name) if bare: work_tree_path = None else: work_tree_path = self._path_work_tree(name) if not os.path.exists(work_tree_path): os.mkdir(work_tree_path) try: CodeDoubanProject.create_git_repo(git_path) except: pass repo = git.GitRepo(git_path, work_tree=work_tree_path) return repo
def setup_repos(tmpdir, prj_name='test_proj'): origin_project = CodeDoubanProject.add(prj_name, 1, create_trac=False) path = origin_project.git_real_path with clone(path) as workdir: with open(os.path.join(workdir, 'origin'), 'w') as f: f.write(content_a) fork_project = CodeDoubanProject.add(prj_name + '_fork', 2, fork_from=origin_project.id, create_trac=False) fork_path = fork_project.git_real_path repo = origin_project fork_repo = fork_project return path, repo, fork_path, fork_repo
def test_get_fork_network_should_return_all_projects_with_same_origin( self): # noqa prj = CodeDoubanProject.get_by_name('orig') prj.delete() orig = CodeDoubanProject.add('orig', owner_id="test1") fork = orig.fork('fork1', 'user1') fork2 = orig.fork('fork2', 'user2') fork3 = fork.fork('fork3', 'user3') expected_network = set([orig, fork, fork2, fork3]) for proj in [orig, fork, fork2, fork3]: network = proj.get_fork_network() eq_(set(network), expected_network)
def test_get_my_projects(self): project_name = "code" product_name = "fire" summary = "test" owner_id = "xingben" for i in range(5): delete_project("%s%d" % (project_name, i)) CodeDoubanProject.add("%s%d" % (project_name, i), owner_id=owner_id, summary=summary, product=product_name) api_token = self.create_api_token("xingben") ret = self.app.get( "/api/user/repos", headers=dict(Authorization="Bearer %s" % api_token.token), status=200 ).json self.assertEquals(len(ret), 5) self.assertTrue("name" in ret[0]) self.assertTrue("description" in ret[0])
def _repo(self, name, bare=True): git_path = self._path(name) if bare: work_tree_path = None else: work_tree_path = self._path_work_tree(name) if os.path.exists(git_path): shutil.rmtree(git_path, ignore_errors=True) try: os.mkdir(work_tree_path) except OSError: pass CodeDoubanProject.create_git_repo(git_path) repo = git.GitRepo(git_path, work_tree=work_tree_path) return repo
def unwatch(request): user = request.user if not user: return request.redirect("/") errors = "" if request.method == "POST": proj_id = request.get_form_var('proj_id') CodeDoubanProject.del_watch(proj_id, user.name) project = CodeDoubanProject.get(proj_id) return request.redirect('/%s/' % project.name) proj_id = request.get_form_var('proj_id') or "" project = CodeDoubanProject.get(proj_id) action = "unwatch" return st('watch.html', **locals())
def test_add_hook(self): url = "http://this.is.a.url" prj = self._prj() hook = CodeDoubanHook.add(url, prj.id) hooked_project = CodeDoubanProject.get(hook.project_id) assert hooked_project assert hook.__dict__ == hooked_project.hooks[0].__dict__
def create(self, request): if request.method == 'POST': user = request.user if not user: raise AccessError project = request.get_form_var('project') title = request.get_form_var('title', '').decode('utf-8') description = request.get_form_var('body', '').decode('utf-8') tags = request.get_form_var('issue_tags', []) if isinstance(tags, list): tags = [tag.decode('utf-8') for tag in tags if tag] elif isinstance(tags, basestring): tags = [tags.decode('utf-8')] if not project: raise TraversalError if not title.strip(): return request.redirect('/%s/issues/new?error=empty' % project) project = CodeDoubanProject.get_by_name(project) pissue = ProjectIssue.add(title, description, user.name, project=project.id) pissue.add_tags(tags, pissue.project_id) # TODO: 重构feed后取消信号发送 issue_signal.send(author=user.name, content=description, issue_id=pissue.issue_id) dispatch('issue', data={ 'sender': user.name, 'content': description, 'issue': pissue }) return request.redirect(pissue.url) project_name = self.proj_name return request.redirect('/%s/issues' % project_name)
def __init__(self, data): NotificationDispatcher.__init__(self, data) self._comment = data.get('comment') # TODO: get commit author by sha # ...现在应该是 None self._commit_author = data.get('commit_author') self._is_line_comment = data.get('is_line_comment') # no use self._proj = CodeDoubanProject.get(self._comment.project_id)
def _get_tmpl_raw(tmpl_target, rev, path, project_name, request): project = CodeDoubanProject.get_by_name(project_name) if rev is None: rev = project.default_branch try: blob = project.repo.get_file(rev, path.decode('utf-8')) except IOError: raise TraversalError() if not blob: raise TraversalError("No content found") resp = request.response if is_image(path): if path.endswith('svg'): resp.set_header("Content-Type", "image/svg+xml") else: resp.set_header("Content-Type", "image/jpeg") resp.set_header('Expires', 'Sun, 1 Jan 2006 01:00:00 GMT') resp.set_header('Pragma', 'no-cache') resp.set_header('Cache-Control', 'must-revalidate, no-cache, private') return blob.data if path.endswith('.pdf'): resp.set_header("Content-Type", "application/pdf") return blob.data if is_binary(path): resp.set_header("Content-Type", "application/octet-stream") resp.set_header("Content-Disposition", "attachment;filename=%s" % path.split('/')[-1]) resp.set_header("Content-Transfer-Encoding", "binary") return blob.data resp.set_header("Content-Type", "text/plain;charset=utf-8") return blob.data.encode('utf8')
def projects(self, request): projects = CodeDoubanProject.gets_by_owner_id(self.user.username) data = [] without_commits = request.get_form_var('without_commits') for project in projects: data.append(project.get_info(without_commits)) return data
def delete_project(names): if isinstance(names, basestring): names = [names] for n in names: prj = CodeDoubanProject.get_by_name(n) if prj: prj.delete()
def test_project_stat(self): store.execute("delete from codedouban_projects where project_id < 5") project_rs = get_all_project() assert len(project_rs) == 0 project_fork_count = len(filter(lambda x: x[1] is not None, project_rs)) assert project_fork_count == 0 project_name = "project" project = CodeDoubanProject.add( project_name, owner_id="test1", summary="test", product="fire") git_path = os.path.join(get_repo_root(), '%s.git' % project_name) ok_(os.path.exists(git_path)) project_rs = get_all_project() assert len(project_rs) == 1 project_fork_count = len(filter(lambda x: x[1] is not None, project_rs)) assert project_fork_count == 0 project_fork = project.fork('project_test_fork', 'test_fork') project_rs = get_all_project() assert len(project_rs) == 2 project_fork_count = len(filter(lambda x: x[1] is not None, project_rs)) assert project_fork_count == 1 project.delete() project_fork.delete()
def has_permission_handler(username, path, perm): if not username or not path: return False if path.endswith(".git"): path = path[:-4] # gist if path.startswith("gist/"): gist_id = path.rpartition("/")[-1] if username == Gist.get(gist_id).owner_id: return True return False # project project = Project.get_by_name(path) if not project: return False if perm == "read": return True if not project.can_push: return False if project.has_push_perm(username): return True return False
def setup_repos(tmpdir, prj_name='test_proj'): delete_project(prj_name) origin_project = CodeDoubanProject.add(prj_name, 1, create_trac=False) path = origin_project.git_real_path with clone(path) as workdir: with open(os.path.join(workdir, 'origin'), 'w') as f: f.write(content_a) delete_project(prj_name + '_fork') fork_project = CodeDoubanProject.add(prj_name + '_fork', 2, fork_from=origin_project.id, create_trac=False) fork_path = fork_project.git_real_path repo = origin_project fork_repo = fork_project return path, repo, fork_path, fork_repo
def setUp(self): super(ProjectIssueCommentsTest, self).setUp() project_name = "code" product_name = "fire" summary = "test" owner_id = "lisong_intern" delete_project(project_name) project = CodeDoubanProject.add( project_name, owner_id=owner_id, summary=summary, product=product_name ) self.project = project title = "test title" description = "test desc" creator = "test" issue = ProjectIssue.add( title, description, creator, project=self.project.id ) self.issue = issue self.project = project self.comment1 = IssueComment.add( self.issue.issue_id, 'content1', 'test1') self.comment2 = IssueComment.add( self.issue.issue_id, 'content2', 'test2') self.api_token = self.create_api_token('test1') self.api_token2 = self.create_api_token('test2')
def _tmpl_common_data(rev, path, project_name, request): project = CodeDoubanProject.get_by_name(project_name) user = request.user ref = rev if ref is None: ref = project.default_branch branches = project.repo.branches tags = project.repo.tags ref_type = 'branch' if ref in branches else 'tag' \ if ref in tags else 'tree' blob_path = path.decode('utf-8') tdt = { 'errors': '', 'branches': branches, 'rev': rev, 'tags': tags, 'blob_path': blob_path, 'file_name': blob_path.rpartition('/')[-1], 'request': request, 'project': project, 'project_name': project_name, 'path': path, 'ref_type': ref_type, 'blob_ref': ref, 'ref': ref, 'user': user, } return tdt
def _get_tmpl_raw(tmpl_target, rev, path, project_name, request): project = CodeDoubanProject.get_by_name(project_name) if rev is None: rev = project.default_branch try: blob = project.repo.get_file(rev, path.decode("utf-8")) except IOError: raise TraversalError() if not blob: raise TraversalError("No content found") resp = request.response if is_image(path): if path.endswith("svg"): resp.set_header("Content-Type", "image/svg+xml") else: resp.set_header("Content-Type", "image/jpeg") resp.set_header("Expires", "Sun, 1 Jan 2006 01:00:00 GMT") resp.set_header("Pragma", "no-cache") resp.set_header("Cache-Control", "must-revalidate, no-cache, private") return blob.data if path.endswith(".pdf"): resp.set_header("Content-Type", "application/pdf") return blob.data if is_binary(path): resp.set_header("Content-Type", "application/octet-stream") resp.set_header("Content-Disposition", "attachment;filename=%s" % path.split("/")[-1]) resp.set_header("Content-Transfer-Encoding", "binary") return blob.data resp.set_header("Content-Type", "text/plain;charset=utf-8") return blob.data.encode("utf8")
def related_projects(self): rs = store.execute( 'select project_id from issue_related_projects ' 'where issue_id=%s', (self.issue_id, )) prj_ids = [id for (id, ) in rs] from vilya.models.project import CodeDoubanProject return CodeDoubanProject.gets(prj_ids)
def async_comment_to_pr(data): ''' commit comment rewrite to pr ''' type_ = data.get('type') if type_ not in ('commit_comment', 'commit_linecomment'): return comment = data.get('comment') ref = comment.get('ref') author = comment.get('author') content = comment.get('content') proj_id = comment.get('project_id') comment_uid = comment.get('comment_uid') proj = CodeDoubanProject.get(proj_id) prs = proj.open_family_pulls anchor = comment_uid for pr in prs: if ref in pr.get_commits_shas(): content = COMMENT_TEMPLATE.format(content=content, domain=DOMAIN, proj=proj.name, sha=ref, anchor=anchor) ticket = Ticket.get_by_projectid_and_ticketnumber( pr.to_proj.id, pr.ticket_id) ticket.add_comment(content, author)
def test_project_stat(self): store.execute("delete from codedouban_projects where project_id < 5") project_rs = get_all_project() assert len(project_rs) == 0 project_fork_count = len(filter(lambda x: x[1] is not None, project_rs)) assert project_fork_count == 0 project_name = "project" project = CodeDoubanProject.add(project_name, owner_id="test1", summary="test", product="fire") git_path = os.path.join(get_repo_root(), '%s.git' % project_name) ok_(os.path.exists(git_path)) project_rs = get_all_project() assert len(project_rs) == 1 project_fork_count = len(filter(lambda x: x[1] is not None, project_rs)) assert project_fork_count == 0 project_fork = project.fork('project_test_fork', 'test_fork') project_rs = get_all_project() assert len(project_rs) == 2 project_fork_count = len(filter(lambda x: x[1] is not None, project_rs)) assert project_fork_count == 1 project.delete() project_fork.delete()
def __init__(self, ticket): self.project = CodeDoubanProject.get(ticket.project_id) self.proj_name = self.project.name self.ticket_id = ticket.ticket_number self.ticket = ticket self.pullreq = PullRequest.get_by_proj_and_ticket( self.project.id, self.ticket_id)