[Tracker-discuss] [issue621] Pull request reopened but the PR still shows closed in bug tracker

2017-03-23 Thread Anish Shah

Anish Shah added the comment:

I can work on this! :)

--
nosy: +anish.shah, maciej.szulik
status: unread -> chatting

___
PSF Meta Tracker <metatrac...@psf.upfronthosting.co.za>
<http://psf.upfronthosting.co.za/roundup/meta/issue621>
___
___
Tracker-discuss mailing list
Tracker-discuss@python.org
https://mail.python.org/mailman/listinfo/tracker-discuss
Code of Conduct: https://www.python.org/psf/codeofconduct/


[Tracker-discuss] [issue614] Duplicate commit message on branch merge

2017-02-17 Thread Anish Shah

Anish Shah added the comment:

Hi Ezio, can you tell me which webhook was triggered? Was it pull request
event?

___
PSF Meta Tracker <metatrac...@psf.upfronthosting.co.za>
<http://psf.upfronthosting.co.za/roundup/meta/issue614>
___
___
Tracker-discuss mailing list
Tracker-discuss@python.org
https://mail.python.org/mailman/listinfo/tracker-discuss
Code of Conduct: https://www.python.org/psf/codeofconduct/


[Tracker-discuss] [issue589] Add GitHub PR to b.p.o issues using GitHub webhooks (depends on issue586)

2016-12-19 Thread Anish Shah

Anish Shah added the comment:

I tested the latest patch on the my repository and it is working properly.
:)

___
PSF Meta Tracker <metatrac...@psf.upfronthosting.co.za>
<http://psf.upfronthosting.co.za/roundup/meta/issue589>
___
___
Tracker-discuss mailing list
Tracker-discuss@python.org
https://mail.python.org/mailman/listinfo/tracker-discuss
Code of Conduct: https://www.python.org/psf/codeofconduct/


[Tracker-discuss] [issue586] Add GitHub Pull Request URL on issue page

2016-12-01 Thread Anish Shah

Anish Shah added the comment:

Hi, on this link http://bugs.python.org/pull_request, I am getting a textbox 
where I can delete/edit entries. Do we want this? I am not sure.

___
PSF Meta Tracker <metatrac...@psf.upfronthosting.co.za>
<http://psf.upfronthosting.co.za/roundup/meta/issue586>
___
___
Tracker-discuss mailing list
Tracker-discuss@python.org
https://mail.python.org/mailman/listinfo/tracker-discuss
Code of Conduct: https://www.python.org/psf/codeofconduct/


[Tracker-discuss] [issue600] Convert patches to GitHub Pull Request (depends on issue586)

2016-08-22 Thread Anish Shah

Anish Shah added the comment:

I have updated the patch.

> We do need proper error handling, still.
The problem is "err" variable has stdout of that process. So, even if we 
change/push branch, it will be non-empty. Any idea how to solve this problem?

One more thing, if we create PR using API, it triggers GitHub webhooks. So, I'm 
removing the part where we are storing the response in DB.

Also, I'm not sure how to add tests for this.

--
title: Convert patches to GitHub Pull Request -> Convert patches to GitHub Pull 
Request (depends on issue586)

___
PSF Meta Tracker <metatrac...@psf.upfronthosting.co.za>
<http://psf.upfronthosting.co.za/roundup/meta/issue600>
___diff --git a/detectors/patches.py b/detectors/patches.py
index 18d3db4..9e2e01e 100644
--- a/detectors/patches.py
+++ b/detectors/patches.py
@@ -5,10 +5,97 @@
 
 import posixpath
 import identify_patch
+import os
+import subprocess
+import string
+import random
+import json
+import requests
+import tempfile
+import shutil
+import logging
 
 patchtypes = ('.diff', '.patch')
 sourcetypes = ('.diff', '.patch', '.py')
 
+
+class TemporaryDirectory(object):
+
+def __enter__(self):
+self.name = tempfile.mkdtemp()
+return self.name
+
+def __exit__(self, *args):
+shutil.rmtree(self.name)
+
+
+def create_pull_request(db, head, base, issue_id, issue_title):
+endpoint = 'https://api.github.com/repos/python/cpython/pulls'
+access_token = os.environ['ACCESS_TOKEN']
+headers = {'Authorization': 'token {}'.format(access_token)}
+data = json.dumps({
+"title": "{}".format(issue_title),
+"body": "fixes issue bpo{}".format(issue_id),
+"base": base, "head": head})
+response = requests.post(endpoint, headers=headers, data=data)
+if not response.ok:
+logging.error(response.text, exc_info=True)
+raise Exception('Error while creating pull request')
+else:
+response_body = response.json()
+url = response_body['html_url']
+state = response_body['state']
+pr_id = db.pull_request.create(url=url, state=state)
+issue_pr = db.issue.get(issue_id, 'pull_requests')
+issue_pr.append(pr_id)
+db.issue.set(issue_id, pull_requests=issue_pr)
+db.commit()
+
+
+def git_command(command, path):
+process = subprocess.Popen(command, cwd=path, shell=True,
+   stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+out, err = process.communicate()
+# err takes stdout
+# if err:
+# raise Exception(err)
+
+
+def git_workflow(db, issue_id, file_id):
+try:
+path = os.environ['GIT_PATH']
+versions = map(lambda id: (db.version.get(id, 'name'), 
db.version.get(id, 'order')),
+   db.issue.get(issue_id, 'versions'))
+title = db.issue.get(issue_id, 'title')
+commit_msg = 'Fixes issue bpo{} : {}'.format(issue_id, title)
+if len(versions) == 0:
+parent_branch = "master"
+else:
+version = versions.pop()
+if version[1] == 1:
+parent_branch = "master"
+else:
+parent_branch = version[0].split()[1]
+branch_name = ''.join([random.choice(string.ascii_letters) for i in 
range(random.choice(range(10, 20)))])
+with TemporaryDirectory() as temp_dir:
+filepath = os.path.join(temp_dir, db.file.get(file_id, 'name'))
+content = db.file.get(file_id, 'content')
+with open(filepath, 'wb') as fp:
+fp.write(content)
+git_command("git checkout {}".format(parent_branch), path)
+git_command("git checkout -b {}".format(branch_name), path)
+git_command("git apply {}".format(filepath), path)
+git_command("git add -A", path)
+git_command("git commit -m \"{}\"".format(commit_msg), path)
+git_command("git push origin {}".format(branch_name), path)
+git_command("git checkout {}".format(parent_branch), path)
+git_command("git branch -D {}".format(branch_name), path)
+create_pull_request(db, branch_name, parent_branch, issue_id, 
title)
+except Exception, message:
+logging.error(message, exc_info=True)
+raise ValueError('Error!')
+
+
 def ispatch(file, types):
 return posixpath.splitext(file)[1] in types
 
@@ -26,6 +113,7 @@ def patches_keyword(db, cl, nodeid, newvalues):
 for fileid in newfiles:
 if ispatch(db.file.get(fileid, 'name'), patchtypes):
 newpatch = True
+git_workflow(db, nodeid, fileid)
 break
 if 

[Tracker-discuss] [issue592] Show GitHub comments on b.p.o (depends on issue590)

2016-08-22 Thread Anish Shah

Anish Shah added the comment:

Great! :)

___
PSF Meta Tracker <metatrac...@psf.upfronthosting.co.za>
<http://psf.upfronthosting.co.za/roundup/meta/issue592>
___
___
Tracker-discuss mailing list
Tracker-discuss@python.org
https://mail.python.org/mailman/listinfo/tracker-discuss
Code of Conduct: https://www.python.org/psf/codeofconduct/


[Tracker-discuss] [issue592] Show GitHub comments on b.p.o (depends on issue590)

2016-08-20 Thread Anish Shah

Anish Shah added the comment:

I have updated the patch :)

___
PSF Meta Tracker <metatrac...@psf.upfronthosting.co.za>
<http://psf.upfronthosting.co.za/roundup/meta/issue592>
___diff --git a/roundup/pull_request.py b/roundup/pull_request.py
index fc70ca5..f5f8c06 100644
--- a/roundup/pull_request.py
+++ b/roundup/pull_request.py
@@ -1,4 +1,5 @@
 from roundup.exceptions import *
+from roundup import date
 
 import hashlib
 import hmac
@@ -15,6 +16,9 @@ else:
 return a == b
 
 
+valid_events = ('pull_request', 'issue_comment', 'pull_request_review_comment')
+
+
 class GitHubHandler:
 
 def __init__(self, client):
@@ -43,7 +47,7 @@ class GitHubHandler:
 
 def _extract(self):
 event = self._get_event()
-if event not in ('pull_request', 'issue_comment'):
+if event not in valid_events:
 raise Reject('Unkown X-GitHub-Event {}'.format(event))
 data = json.loads(self.form.value)
 if event == 'pull_request':
@@ -52,6 +56,9 @@ class GitHubHandler:
 elif event == 'issue_comment':
 handler = IssueComment(self.db, data)
 handler.dispatch()
+elif event == 'pull_request_review_comment':
+handler = PullRequestReviewComment(self.db, data)
+handler.dispatch()
 
 def _validate_webhook_secret(self):
 key = os.environ['SECRET_KEY']
@@ -95,6 +102,33 @@ class Event:
 self.db.issue.set(issue_id, pull_requests=urls)
 self.db.commit()
 
+def handle_comment(self, comment):
+url = self._get_url()
+issue_id = self._get_issue_id_using_url(url)
+if issue_id is not None:
+user_id = self.db.user.lookup(os.environ.get('GITHUB_COMMENT_USER',
+ 'admin'))
+messages = self.db.issue.get(issue_id, 'messages')
+now = date.Date('.')
+min_date = now - date.Interval(os.environ.get('TIME_INTERVAL',
+  '00:30'))
+date_range_string = str(min_date)+';'+str(now)
+msg_ids = self.db.msg.filter(None, {'is_github_comment': True,
+'creation': date_range_string})
+if not msg_ids:
+msg_id = self.db.msg.create(content=comment, author=user_id,
+date=now, is_github_comment=True)
+messages.append(msg_id)
+self.db.issue.set(issue_id, messages=messages)
+self.db.commit()
+
+def _get_issue_id_using_url(self, url):
+pr_id = self.db.pull_request.filter(None, {'url': url})
+if len(pr_id) == 1:
+issue_id = self.db.issue.filter(None, {'pull_requests': pr_id[0]})
+if len(issue_id) == 1:
+return issue_id[0]
+
 def _get_issue_ids(self):
 raise NotImplementedError
 
@@ -166,8 +200,10 @@ class IssueComment(Event):
 action = self.data['action'].encode('utf-8')
 issue_id = self._get_issue_ids()
 url = self._get_url()
+comment = self._get_comment()
 if action == 'created' and issue_id is not None:
 self.handle_create(url, issue_id)
+self.handle_comment(comment)
 
 def _get_issue_ids(self):
 body = self.data['comment']['body'].encode('utf-8')
@@ -181,3 +217,25 @@ class IssueComment(Event):
 
 def _get_github_username(self):
 return self.data['issue']['user']['login'].encode('utf-8')
+
+def _get_comment(self):
+comment_user = self.data['comment']['user']['login'].encode('utf-8')
+comment = self.data['comment']['body'].encode('utf-8')
+url = self._get_url()
+return '%s left a comment on GitHub:\n\n%s' % (comment_user, url)
+
+
+class PullRequestReviewComment(IssueComment):
+
+def __init__(self, db, data):
+self.db = db
+self.data = data
+
+def dispatch(self):
+action = self.data['action'].encode('utf-8')
+comment = self._get_comment()
+if action == 'created':
+self.handle_comment(comment)
+
+def _get_url(self):
+return self.data['pull_request']['html_url']
diff --git a/share/roundup/templates/classic/schema.py 
b/share/roundup/templates/classic/schema.py
index 34ae90b..9b548fb 100644
--- a/share/roundup/templates/classic/schema.py
+++ b/share/roundup/templates/classic/schema.py
@@ -61,7 +61,8 @@ msg = FileClass(db, "msg",
 summary=String(),
 files=Multilink("file"),
 messageid=String(),
-inreplyto=String())
+inreplyto=String(),
+is_github_comment=Boolean())
 
 file = FileClass(db, "file",
 name=String())
diff --git a

[Tracker-discuss] [issue592] Show GitHub comments on b.p.o (depends on issue590)

2016-08-20 Thread Anish Shah

Anish Shah added the comment:

> It would be nice to have the user configurable, not admin hardcoded.

By configurable, do you mean creating an env var?

___
PSF Meta Tracker <metatrac...@psf.upfronthosting.co.za>
<http://psf.upfronthosting.co.za/roundup/meta/issue592>
___
___
Tracker-discuss mailing list
Tracker-discuss@python.org
https://mail.python.org/mailman/listinfo/tracker-discuss
Code of Conduct: https://www.python.org/psf/codeofconduct/


[Tracker-discuss] [issue592] Show GitHub comments on b.p.o (depends on issue590)

2016-08-18 Thread Anish Shah

Anish Shah added the comment:

I have updated the patch.
now, GitHub name, comment and link to the PR will be posted on b.p.o

___
PSF Meta Tracker <metatrac...@psf.upfronthosting.co.za>
<http://psf.upfronthosting.co.za/roundup/meta/issue592>
___diff --git a/roundup/pull_request.py b/roundup/pull_request.py
index fc70ca5..6f92b83 100644
--- a/roundup/pull_request.py
+++ b/roundup/pull_request.py
@@ -1,4 +1,5 @@
 from roundup.exceptions import *
+from roundup import date
 
 import hashlib
 import hmac
@@ -15,6 +16,9 @@ else:
 return a == b
 
 
+valid_events = ('pull_request', 'issue_comment', 'pull_request_review_comment')
+
+
 class GitHubHandler:
 
 def __init__(self, client):
@@ -43,7 +47,7 @@ class GitHubHandler:
 
 def _extract(self):
 event = self._get_event()
-if event not in ('pull_request', 'issue_comment'):
+if event not in valid_events:
 raise Reject('Unkown X-GitHub-Event {}'.format(event))
 data = json.loads(self.form.value)
 if event == 'pull_request':
@@ -52,6 +56,9 @@ class GitHubHandler:
 elif event == 'issue_comment':
 handler = IssueComment(self.db, data)
 handler.dispatch()
+elif event == 'pull_request_review_comment':
+handler = PullRequestReviewComment(self.db, data)
+handler.dispatch()
 
 def _validate_webhook_secret(self):
 key = os.environ['SECRET_KEY']
@@ -95,6 +102,32 @@ class Event:
 self.db.issue.set(issue_id, pull_requests=urls)
 self.db.commit()
 
+def handle_comment(self, comment):
+url = self._get_url()
+issue_id = self._get_issue_id_using_url(url)
+if issue_id is not None:
+user_id = self.db.user.lookup("admin")
+messages = self.db.issue.get(issue_id, "messages")
+now = date.Date(".")
+min_date = now - date.Interval("00:30")
+date_range_string = "from " + str(min_date)
+msg_ids = self.db.msg.filter(None, {"is_github_comment": True,
+"creation": date_range_string})
+if not bool(msg_ids):
+msg_id = self.db.msg.create(content=comment, author=user_id,
+date=now, is_github_comment=True)
+messages.append(msg_id)
+self.db.issue.set(issue_id, messages=messages)
+self.db.commit()
+
+def _get_issue_id_using_url(self, url):
+pr_id = self.db.pull_request.filter(None, {'url': url})
+pr_exists = len(pr_id) == 1
+if pr_exists:
+issue_id = self.db.issue.filter(None, {'pull_requests': pr_id[0]})
+if len(issue_id) == 1:
+return issue_id[0]
+
 def _get_issue_ids(self):
 raise NotImplementedError
 
@@ -166,8 +199,10 @@ class IssueComment(Event):
 action = self.data['action'].encode('utf-8')
 issue_id = self._get_issue_ids()
 url = self._get_url()
+comment = self._get_comment()
 if action == 'created' and issue_id is not None:
 self.handle_create(url, issue_id)
+self.handle_comment(comment)
 
 def _get_issue_ids(self):
 body = self.data['comment']['body'].encode('utf-8')
@@ -181,3 +216,26 @@ class IssueComment(Event):
 
 def _get_github_username(self):
 return self.data['issue']['user']['login'].encode('utf-8')
+
+def _get_comment(self):
+comment_user = self.data['comment']['user']['login'].encode('utf-8')
+comment = self.data['comment']['body'].encode('utf-8')
+url = self._get_url()
+return '%s left a comment on GitHub:\n\n%s\n\n%s' % (comment_user,
+ comment, url)
+
+
+class PullRequestReviewComment(IssueComment):
+
+def __init__(self, db, data):
+self.db = db
+self.data = data
+
+def dispatch(self):
+action = self.data['action'].encode('utf-8')
+comment = self._get_comment()
+if action == 'created':
+self.handle_comment(comment)
+
+def _get_url(self):
+return self.data['pull_request']['html_url']
diff --git a/share/roundup/templates/classic/schema.py 
b/share/roundup/templates/classic/schema.py
index 34ae90b..9b548fb 100644
--- a/share/roundup/templates/classic/schema.py
+++ b/share/roundup/templates/classic/schema.py
@@ -61,7 +61,8 @@ msg = FileClass(db, "msg",
 summary=String(),
 files=Multilink("file"),
 messageid=String(),
-inreplyto=String())
+inreplyto=String(),
+is_github_comment=Boolean())
 
 file = FileClass(db, &q

[Tracker-discuss] [issue592] Show GitHub comments on b.p.o (depends on issue590)

2016-08-16 Thread Anish Shah

Anish Shah added the comment:

I have updated the patch so that it applies cleanly.
I will add the suggestions in a few days.

___
PSF Meta Tracker <metatrac...@psf.upfronthosting.co.za>
<http://psf.upfronthosting.co.za/roundup/meta/issue592>
___diff --git a/roundup/pull_request.py b/roundup/pull_request.py
index fc70ca5..e8af62a 100644
--- a/roundup/pull_request.py
+++ b/roundup/pull_request.py
@@ -1,4 +1,5 @@
 from roundup.exceptions import *
+from roundup import date
 
 import hashlib
 import hmac
@@ -15,6 +16,9 @@ else:
 return a == b
 
 
+valid_events = ('pull_request', 'issue_comment', 'pull_request_review_comment')
+
+
 class GitHubHandler:
 
 def __init__(self, client):
@@ -43,7 +47,7 @@ class GitHubHandler:
 
 def _extract(self):
 event = self._get_event()
-if event not in ('pull_request', 'issue_comment'):
+if event not in valid_events:
 raise Reject('Unkown X-GitHub-Event {}'.format(event))
 data = json.loads(self.form.value)
 if event == 'pull_request':
@@ -52,6 +56,9 @@ class GitHubHandler:
 elif event == 'issue_comment':
 handler = IssueComment(self.db, data)
 handler.dispatch()
+elif event == 'pull_request_review_comment':
+handler = PullRequestReviewComment(self.db, data)
+handler.dispatch()
 
 def _validate_webhook_secret(self):
 key = os.environ['SECRET_KEY']
@@ -95,6 +102,32 @@ class Event:
 self.db.issue.set(issue_id, pull_requests=urls)
 self.db.commit()
 
+def handle_comment(self, comment):
+url = self._get_url()
+issue_id = self._get_issue_id_using_url(url)
+if issue_id is not None:
+user_id = self.db.user.lookup("admin")
+messages = self.db.issue.get(issue_id, "messages")
+now = date.Date(".")
+min_date = now - date.Interval("00:30")
+date_range_string = "from " + str(min_date)
+msg_ids = self.db.msg.filter(None, {"is_github_comment": True,
+"creation": date_range_string})
+if not bool(msg_ids):
+msg_id = self.db.msg.create(content=comment, author=user_id,
+date=now, is_github_comment=True)
+messages.append(msg_id)
+self.db.issue.set(issue_id, messages=messages)
+self.db.commit()
+
+def _get_issue_id_using_url(self, url):
+pr_id = self.db.pull_request.filter(None, {'url': url})
+pr_exists = len(pr_id) == 1
+if pr_exists:
+issue_id = self.db.issue.filter(None, {'pull_requests': pr_id[0]})
+if len(issue_id) == 1:
+return issue_id[0]
+
 def _get_issue_ids(self):
 raise NotImplementedError
 
@@ -166,8 +199,10 @@ class IssueComment(Event):
 action = self.data['action'].encode('utf-8')
 issue_id = self._get_issue_ids()
 url = self._get_url()
+comment = self._get_comment()
 if action == 'created' and issue_id is not None:
 self.handle_create(url, issue_id)
+self.handle_comment(comment)
 
 def _get_issue_ids(self):
 body = self.data['comment']['body'].encode('utf-8')
@@ -181,3 +216,26 @@ class IssueComment(Event):
 
 def _get_github_username(self):
 return self.data['issue']['user']['login'].encode('utf-8')
+
+def _get_comment(self):
+comment_user = self.data['comment']['user']['login'].encode('utf-8')
+comment = self.data['comment']['body'].encode('utf-8')
+url = self.data['comment']['html_url'].encode('utf-8')
+return '%s left a comment on GitHub:\n\n%s\n\n%s' % (comment_user,
+ comment, url)
+
+
+class PullRequestReviewComment(IssueComment):
+
+def __init__(self, db, data):
+self.db = db
+self.data = data
+
+def dispatch(self):
+action = self.data['action'].encode('utf-8')
+comment = self._get_comment()
+if action == 'created':
+self.handle_comment(comment)
+
+def _get_url(self):
+return self.data['pull_request']['html_url']
diff --git a/share/roundup/templates/classic/schema.py 
b/share/roundup/templates/classic/schema.py
index 34ae90b..9b548fb 100644
--- a/share/roundup/templates/classic/schema.py
+++ b/share/roundup/templates/classic/schema.py
@@ -61,7 +61,8 @@ msg = FileClass(db, "msg",
 summary=String(),
 files=Multilink("file"),
 messageid=String(),
-inreplyto=String())
+inreplyto=String(),
+is_github_com

[Tracker-discuss] [issue589] Add GitHub PR to b.p.o issues using GitHub webhooks (depends on issue586)

2016-08-12 Thread Anish Shah

Anish Shah added the comment:

I have updated the patch with all three changes

___
PSF Meta Tracker <metatrac...@psf.upfronthosting.co.za>
<http://psf.upfronthosting.co.za/roundup/meta/issue589>
___diff --git a/roundup/cgi/client.py b/roundup/cgi/client.py
index e71983d..abfbf51 100644
--- a/roundup/cgi/client.py
+++ b/roundup/cgi/client.py
@@ -22,6 +22,7 @@ from roundup.cgi.form_parser import FormParser
 from roundup.mailer import Mailer, MessageSendError, encode_quopri
 from roundup.cgi import accept_language
 from roundup import xmlrpc
+from roundup.pull_request import GitHubHandler
 
 from roundup.anypy.cookie_ import CookieError, BaseCookie, SimpleCookie, \
 get_cookie_date
@@ -378,6 +379,8 @@ class Client:
 try:
 if self.path == 'xmlrpc':
 self.handle_xmlrpc()
+elif self.path == 'pull_request':
+self.handle_pull_request()
 else:
 self.inner_main()
 finally:
@@ -385,6 +388,34 @@ class Client:
 self.db.close()
 
 
+def handle_pull_request(self):
+# Set the charset and language, since other parts of
+# Roundup may depend upon that.
+self.determine_charset()
+self.determine_language()
+# Open the database as the correct user.
+self.determine_user()
+self.check_anonymous_access()
+
+try:
+handler = GitHubHandler(self)
+handler.dispatch()
+except Unauthorised, message:
+self.response_code = 403
+self.write(message)
+except UnsupportedMediaType, message:
+self.response_code = 415
+self.write(message)
+except MethodNotAllowed, message:
+self.response_code = 405
+self.write(message)
+except Reject, message:
+self.response_code = 400
+self.write(message)
+else:
+self.write("Done!")
+
+
 def handle_xmlrpc(self):
 if self.env.get('CONTENT_TYPE') != 'text/xml':
 self.write("This is the endpoint of Roundup https://api.github.com/repos/AnishShah/cpython/issues/1","repository_url":"https://api.github.com/repos/AnishShah/cpython","labels_url":"https://api.github.com/repos/AnishShah/cpython/issues/1/labels{/name}","comments_url":"https://api.github.com/repos/AnishShah/cpython/issues/1/comments","events_url":"https://api.github.com/repos/AnishShah/cpython/issues/1/events","html_url":"https://github.com/AnishShah/cpython/pull/1","id":156471938,"number":1,"title":"Test","user":{"login":"AnishShah","id":3175743,"avatar_url":"https://avatars.githubusercontent.com/u/3175743?v=3","gravatar_id":"","url":"https://api.github.com/users/AnishShah","html_url":"https://github.com/AnishShah","followers_url":"https://api.github.com/users/AnishShah/followers","following_url":"https://api.github.com/users/AnishShah/following{/other_user}","gists_url":"https://api.github.com/users/AnishShah/gists{/gist_id}","starred_url":"https://api.github.com/users/AnishShah/sta
 
rred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AnishShah/subscriptions","organizations_url":"https://api.github.com/users/AnishShah/orgs","repos_url":"https://api.github.com/users/AnishShah/repos","events_url":"https://api.github.com/users/AnishShah/events{/privacy}","received_events_url":"https://api.github.com/users/AnishShah/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2016-05-24T10:22:11Z","updated_at":"2016-05-31T09:05:10Z","closed_at":"2016-05-24T10:23:56Z","pull_request":{"url":"https://api.github.com/repos/AnishShah/cpython/pulls/1","html_url":"https://github.com/AnishShah/cpython/pull/1","diff_url":"https://github.com/AnishShah/cpython/pull/1.diff","patch_url":"https://github.com/AnishShah/cpython/pull/1.patch"},"body":""},"comment":{"url":"https://api.github.com/repos/AnishShah/cpython/issues/comments/222632341","html_url":"https://g
 
ithub.com/AnishShah/cpython/pull/1#issuec

[Tracker-discuss] [issue589] Add GitHub PR to b.p.o issues using GitHub webhooks (depends on issue586)

2016-08-11 Thread Anish Shah

Anish Shah added the comment:

Oops. Got it now. I will include the changes.

___
PSF Meta Tracker <metatrac...@psf.upfronthosting.co.za>
<http://psf.upfronthosting.co.za/roundup/meta/issue589>
___
___
Tracker-discuss mailing list
Tracker-discuss@python.org
https://mail.python.org/mailman/listinfo/tracker-discuss
Code of Conduct: https://www.python.org/psf/codeofconduct/


[Tracker-discuss] [issue589] Add GitHub PR to b.p.o issues using GitHub webhooks (depends on issue586)

2016-08-10 Thread Anish Shah

Anish Shah added the comment:

new tests:
- secret key missing
- Github event missing in header
- non json body
- multiple references in PR body
- CREATE_ISSUE is not set and no issue is reference in PR
- if github field of user is set, then PR/issue is assigned to that user or 
else anonymous

___
PSF Meta Tracker <metatrac...@psf.upfronthosting.co.za>
<http://psf.upfronthosting.co.za/roundup/meta/issue589>
___commit a565735c6ebbb0a664cd7f9e5b68a406094ecf0f
Author: Anish Shah <shah.anis...@gmail.com>
Date:   Wed Jul 27 00:03:46 2016 +0530

Add GitHub PR to bpo using webhooks

diff --git a/roundup/cgi/client.py b/roundup/cgi/client.py
index e71983d..abfbf51 100644
--- a/roundup/cgi/client.py
+++ b/roundup/cgi/client.py
@@ -22,6 +22,7 @@ from roundup.cgi.form_parser import FormParser
 from roundup.mailer import Mailer, MessageSendError, encode_quopri
 from roundup.cgi import accept_language
 from roundup import xmlrpc
+from roundup.pull_request import GitHubHandler
 
 from roundup.anypy.cookie_ import CookieError, BaseCookie, SimpleCookie, \
 get_cookie_date
@@ -378,6 +379,8 @@ class Client:
 try:
 if self.path == 'xmlrpc':
 self.handle_xmlrpc()
+elif self.path == 'pull_request':
+self.handle_pull_request()
 else:
 self.inner_main()
 finally:
@@ -385,6 +388,34 @@ class Client:
 self.db.close()
 
 
+def handle_pull_request(self):
+# Set the charset and language, since other parts of
+# Roundup may depend upon that.
+self.determine_charset()
+self.determine_language()
+# Open the database as the correct user.
+self.determine_user()
+self.check_anonymous_access()
+
+try:
+handler = GitHubHandler(self)
+handler.dispatch()
+except Unauthorised, message:
+self.response_code = 403
+self.write(message)
+except UnsupportedMediaType, message:
+self.response_code = 415
+self.write(message)
+except MethodNotAllowed, message:
+self.response_code = 405
+self.write(message)
+except Reject, message:
+self.response_code = 400
+self.write(message)
+else:
+self.write("Done!")
+
+
 def handle_xmlrpc(self):
 if self.env.get('CONTENT_TYPE') != 'text/xml':
 self.write("This is the endpoint of Roundup https://api.github.com/repos/AnishShah/cpython/issues/1","repository_url":"https://api.github.com/repos/AnishShah/cpython","labels_url":"https://api.github.com/repos/AnishShah/cpython/issues/1/labels{/name}","comments_url":"https://api.github.com/repos/AnishShah/cpython/issues/1/comments","events_url":"https://api.github.com/repos/AnishShah/cpython/issues/1/events","html_url":"https://github.com/AnishShah/cpython/pull/1","id":156471938,"number":1,"title":"Test","user":{"login":"AnishShah","id":3175743,"avatar_url":"https://avatars.githubusercontent.com/u/3175743?v=3","gravatar_id":"","url":"https://api.github.com/users/AnishShah","html_url":"https://github.com/AnishShah","followers_url":"https://api.github.com/users/AnishShah/followers","following_url":"https://api.github.com/users/AnishShah/following{/other_user}","gists_url":"https://api.github.com/users/AnishShah/gists{/gist_id}","starred_url":"https://api.github.com/users/AnishShah/sta
 
rred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AnishShah/subscriptions","organizations_url":"https://api.github.com/users/AnishShah/orgs","repos_url":"https://api.github.com/users/AnishShah/repos","events_url":"https://api.github.com/users/AnishShah/events{/privacy}","received_events_url":"https://api.github.com/users/AnishShah/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2016-05-24T10:22:11Z","updated_at":"2016-05-31T09:05:10Z","closed_at":"2016-05-24T10:23:56Z","pull_request":{"url":"https://api.github.com/repos/AnishShah/cpython/pulls/1","html_url":"https://github.com/AnishShah/cpython/pull/1","

[Tracker-discuss] [issue589] Add GitHub PR to b.p.o issues using GitHub webhooks (depends on issue586)

2016-08-08 Thread Anish Shah

Anish Shah added the comment:

>   * multiple fixes both in title like you have in pullrequestevent3.txt
but also in title

Sorry. I didn't get you. You mean, same tests for PR body, right?

> Is vulnerable to other exceptions, I'm a lazy person and I test your code
with following
> command:
> curl -X POST -H "content-type: application/json" -H "X-GitHub-Event:
pull_request" -d @test/data/pullrequestevent3.txt
http://localhost:/python-dev/pull_request
> doing so I frequently forgot you have additional data in the testfiles
and I'm getting
> "ValueError: No JSON object could be decoded" at this point. Verify other
exceptions
> and throw generic 'Invalid request' in those places (and don't forget to
add tests)

I was thinking of adding "Exception, e" instead of checking for just
KeyError in dispatch method. But that will also catch Unauthorized,
MethodNotAllowed and unsupportedmediatype. Can you suggest a better way to
do this?

___
PSF Meta Tracker <metatrac...@psf.upfronthosting.co.za>
<http://psf.upfronthosting.co.za/roundup/meta/issue589>
___
___
Tracker-discuss mailing list
Tracker-discuss@python.org
https://mail.python.org/mailman/listinfo/tracker-discuss
Code of Conduct: https://www.python.org/psf/codeofconduct/


[Tracker-discuss] [issue589] Add GitHub PR to b.p.o issues using GitHub webhooks (depends on issue586)

2016-08-07 Thread Anish Shah

Anish Shah added the comment:

Should I throw Reject exception if 'SECRET_KEY' is not set as an environment 
variable too?

___
PSF Meta Tracker <metatrac...@psf.upfronthosting.co.za>
<http://psf.upfronthosting.co.za/roundup/meta/issue589>
___
___
Tracker-discuss mailing list
Tracker-discuss@python.org
https://mail.python.org/mailman/listinfo/tracker-discuss
Code of Conduct: https://www.python.org/psf/codeofconduct/


[Tracker-discuss] [issue590] Show Pull Request status on b.p.o (depends on issue586, issue589)

2016-08-01 Thread Anish Shah

Anish Shah added the comment:

I have updated the patch

___
PSF Meta Tracker <metatrac...@psf.upfronthosting.co.za>
<http://psf.upfronthosting.co.za/roundup/meta/issue590>
___
___
Tracker-discuss mailing list
Tracker-discuss@python.org
https://mail.python.org/mailman/listinfo/tracker-discuss
Code of Conduct: https://www.python.org/psf/codeofconduct/


[Tracker-discuss] [issue589] Add GitHub PR to b.p.o issues using GitHub webhooks (depends on issue586)

2016-07-28 Thread Anish Shah

Anish Shah added the comment:

I have added few things to this updated patch:

- load JSON while extracting 
- user who creates GitHub PR will be assigned as PR author on bpo if we find 
github name on bpo or else "anonymous"
- if issue is not referenced in PR title or body and an environment variable is 
set, then a new issue is created on behalf of GitHub PR creator (if we find 
github name on bpo)

___
PSF Meta Tracker <metatrac...@psf.upfronthosting.co.za>
<http://psf.upfronthosting.co.za/roundup/meta/issue589>
___diff --git a/roundup/cgi/client.py b/roundup/cgi/client.py
index e71983d..abfbf51 100644
--- a/roundup/cgi/client.py
+++ b/roundup/cgi/client.py
@@ -22,6 +22,7 @@ from roundup.cgi.form_parser import FormParser
 from roundup.mailer import Mailer, MessageSendError, encode_quopri
 from roundup.cgi import accept_language
 from roundup import xmlrpc
+from roundup.pull_request import GitHubHandler
 
 from roundup.anypy.cookie_ import CookieError, BaseCookie, SimpleCookie, \
 get_cookie_date
@@ -378,6 +379,8 @@ class Client:
 try:
 if self.path == 'xmlrpc':
 self.handle_xmlrpc()
+elif self.path == 'pull_request':
+self.handle_pull_request()
 else:
 self.inner_main()
 finally:
@@ -385,6 +388,34 @@ class Client:
 self.db.close()
 
 
+def handle_pull_request(self):
+# Set the charset and language, since other parts of
+# Roundup may depend upon that.
+self.determine_charset()
+self.determine_language()
+# Open the database as the correct user.
+self.determine_user()
+self.check_anonymous_access()
+
+try:
+handler = GitHubHandler(self)
+handler.dispatch()
+except Unauthorised, message:
+self.response_code = 403
+self.write(message)
+except UnsupportedMediaType, message:
+self.response_code = 415
+self.write(message)
+except MethodNotAllowed, message:
+self.response_code = 405
+self.write(message)
+except Reject, message:
+self.response_code = 400
+self.write(message)
+else:
+self.write("Done!")
+
+
 def handle_xmlrpc(self):
 if self.env.get('CONTENT_TYPE') != 'text/xml':
 self.write("This is the endpoint of Roundup \d+)', re.I)
+
+def handle_create(self, url, issue_id):
+issue_exists = len(self.db.issue.filter(None, {'id': issue_id})) == 1
+url_exists = len(self.db.pull_request.filter(None, {'url': url})) == 1
+if issue_exists and not url_exists:
+url_id = self.db.pull_request.create(url=url)
+urls = self.db.issue.get(issue_id, 'pull_requests')
+urls.append(url_id)
+self.db.issue.set(issue_id, pull_requests=urls)
+self.db.commit()
+
+def _get_issue_id(self):
+raise NotImplementedError
+
+def _get_url(self):
+raise NotImplementedError
+
+
+class PullRequest(Event):
+
+def __init__(self, db, data):
+self.db = db
+self.data = data
+
+def dispatch(self):
+github_username = self._get_github_username()
+user_id = self.db.user.filter(None, {'github': github_username})
+if len(user_id) == 1:
+username = self.db.user.get(user_id[0], 'username')
+self.db.setCurrentUser(username)
+action = self.data['action'].encode('utf-8')
+issue_id = self._get_issue_id()
+url = self._get_url()
+if action == 'opened' and issue_id is not None:
+self.handle_create(url, issue_id)
+
+def _get_issue_id(self):
+title = self.data['pull_request']['title'].encode('utf-8')
+body = self.data['pull_request']['body'].encode('utf-8')
+title_match = self.issue_re.search(title)
+body_match = self.issue_re.search(body)
+if body_match:
+return body_match.group('id')
+elif title_match:
+return title_match.group('id')
+# No issue id found
+create_issue = os.environ.get('CREATE_ISSUE', False)
+if create_issue:
+return self.db.issue.create(title=title)
+return None
+
+def _get_url(self):
+return self.data['pull_request']['html_url'].encode('utf-8')
+
+def _get_github_username(self):
+return self.data['pull_request']['user']['login'].encode('utf-8')
+
+
+class IssueComment(Event):
+
+def __init__(self, db, data):
+self.db = db
+self.data = data
+
+def dispatch(self):
+github_username = self._get_github_username()
+user_id = self.db.user.filter(None, {'github': github_username})
+if len(user_id) == 1:
+

[Tracker-discuss] [issue592] Show GitHub comments on b.p.o

2016-07-27 Thread Anish Shah

Anish Shah added the comment:

Description about this patch:

This patch has a handler to handle GitHub PR review/diff comments event.
First, it checks if any b.p.o issue is linked to this PR or not. Then, it 
checks when was the last time a "GitHub" msg was added. If there are no GitHub 
msg for last "X" minutes (here, 30 minutes), only then this comment is added to 
b.p.o. issue.

___
PSF Meta Tracker <metatrac...@psf.upfronthosting.co.za>
<http://psf.upfronthosting.co.za/roundup/meta/issue592>
___
___
Tracker-discuss mailing list
Tracker-discuss@python.org
https://mail.python.org/mailman/listinfo/tracker-discuss
Code of Conduct: https://www.python.org/psf/codeofconduct/


[Tracker-discuss] [issue589] Add GitHub PR to b.p.o issues using GitHub webhooks (depends on issue586)

2016-07-27 Thread Anish Shah

Anish Shah added the comment:

> Maybe put the code in with a switch so we can turn it on and off?  I'm
pretty sure we're going to want it, but not positive.

Sorry. I didn't get you. What do you want to turn on and off?

___
PSF Meta Tracker <metatrac...@psf.upfronthosting.co.za>
<http://psf.upfronthosting.co.za/roundup/meta/issue589>
___
___
Tracker-discuss mailing list
Tracker-discuss@python.org
https://mail.python.org/mailman/listinfo/tracker-discuss
Code of Conduct: https://www.python.org/psf/codeofconduct/


[Tracker-discuss] [issue589] Add GitHub PR to b.p.o issues using GitHub webhooks (depends on issue586)

2016-07-27 Thread Anish Shah

Anish Shah added the comment:

Thank you for the review. I will update the patch.

@David

I can create a new issue if there's no issue number mentioned.

But as Brett said that someone might forget to add issue number. I'm
currently checking for issue id in PR title, body and issue comments. So, a
reviewer/contributor can add a comment "fixes bpoNN" later on.

Also, GitHub provides a template system [1] where we can ask the
contributor to mention issue number and also whether this is a
documentation PR. This might reduce the noise as mentioned by Berker &
Brett. But, there will always be someone who won't follow the template
system.

[1] https://github.com/blog/2111-issue-and-pull-request-templates

___
PSF Meta Tracker <metatrac...@psf.upfronthosting.co.za>
<http://psf.upfronthosting.co.za/roundup/meta/issue589>
___
___
Tracker-discuss mailing list
Tracker-discuss@python.org
https://mail.python.org/mailman/listinfo/tracker-discuss
Code of Conduct: https://www.python.org/psf/codeofconduct/


[Tracker-discuss] [issue587] Link GitHub pull requests in comments (depends on issue 586)

2016-07-20 Thread Anish Shah
<pre>
Anish Shah added the comment:

I have updated the patch. :)

___
PSF Meta Tracker <metatrac...@psf.upfronthosting.co.za>
<<a  rel="nofollow" href="http://psf.upfronthosting.co.za/roundup/meta/issue587">http://psf.upfronthosting.co.za/roundup/meta/issue587</a>>
___</pre><pre>diff --git a/extensions/local_replace.py b/extensions/local_replace.py
index 1dd0e89..b05e3d4 100644
--- a/extensions/local_replace.py
+++ b/extensions/local_replace.py
@@ -111,6 +111,10 @@ substitutions = [
 # if the issue number is too big the db will explode -- limit it to 7 digits
 issue_re = 
re.compile(r'(?P<text>(\#|\b(?<![-/_])issue)\s*(?P<id>1?\d{1,6}))\b', re.I)
 
+# PR number, pull request number, pullrequest number
+pullrequest_re = 
re.compile(r'(?P<text>(\b(?<![-/_])(PR|pull\s*request))\s*(?P<pr_no>1?\d{1,6}))\b',
+re.I)
+
 
 class PyDevStringHTMLProperty(StringHTMLProperty):
 def _hyper_repl(self, match):
@@ -142,6 +146,7 @@ class PyDevStringHTMLProperty(StringHTMLProperty):
 message = cre.sub(replacement, message)
 # finally add links for issues
 message = issue_re.sub(self._linkify_issue, message)
+message = pullrequest_re.sub(self._linkify_pull_request, message)
 return message
 
 def _linkify_issue(self, match):
@@ -165,6 +170,15 @@ class PyDevStringHTMLProperty(StringHTMLProperty):
 return template % dict(issue_id=issue_id, title=title,
status=status, text=text)
 
+def _linkify_pull_request(self, match):
+"""Turn a pullrequest (e.g. 'PR 123') to an HTML link"""
+template = ('<a href="%(link)s" target="_blank">%(text)s</a>')
+pr_no = match.group('pr_no')
+text = match.group('text')
+base_url = '<a  rel="nofollow" href="https://github.com/python/cpython/pull/{}">https://github.com/python/cpython/pull/{}</a>'
+pr_url = base_url.format(pr_no)
+return template % dict(link=pr_url, text=text)
+
 
 noise_changes = re.compile('(nosy_count|message_count)\: \d+\.0( -> \d+\.0)?')
 
diff --git a/extensions/test/local_replace_data.txt 
b/extensions/test/local_replace_data.txt
index bdf1eb9..dbedc6c 100644
--- a/extensions/test/local_replace_data.txt
+++ b/extensions/test/local_replace_data.txt
@@ -234,3 +234,9 @@ see devguide/committing.html#using-several-working-copies
 see <a 
href="<a  rel="nofollow" href="http://docs.python.org/devguide/committing.html#using-several-working-copies&quot">http://docs.python.org/devguide/committing.html#using-several-working-copies&quot</a>;>devguide/committing.html#using-several-working-copies</a>
 see devguide/committing#using-several-working-copies
 see <a 
href="<a  rel="nofollow" href="http://docs.python.org/devguide/committing#using-several-working-copies&quot">http://docs.python.org/devguide/committing#using-several-working-copies&quot</a>;>devguide/committing#using-several-working-copies</a>
+check my pullrequest 1000 on github
+check my <a href="<a  rel="nofollow" href="https://github.com/python/cpython/pull/1000&quot">https://github.com/python/cpython/pull/1000&quot</a>; 
target="_blank">pullrequest 1000</a> on github
+check my PR 1000 on github
+check my <a href="<a  rel="nofollow" href="https://github.com/python/cpython/pull/1000&quot">https://github.com/python/cpython/pull/1000&quot</a>; 
target="_blank">PR 1000</a> on github
+check my pull request 1000 on github
+check my <a href="<a  rel="nofollow" href="https://github.com/python/cpython/pull/1000&quot">https://github.com/python/cpython/pull/1000&quot</a>; 
target="_blank">pull request 1000</a> on github
</pre><pre>___
Tracker-discuss mailing list
Tracker-discuss@python.org
<a  rel="nofollow" href="https://mail.python.org/mailman/listinfo/tracker-discuss">https://mail.python.org/mailman/listinfo/tracker-discuss</a>
Code of Conduct: <a  rel="nofollow" href="https://www.python.org/psf/codeofconduct/">https://www.python.org/psf/codeofconduct/</a></pre>

[Tracker-discuss] [issue586] Add GitHub Pull Request URL on issue page

2016-07-19 Thread Anish Shah

Anish Shah added the comment:

I have updated the patch according to reviews suggested by @maciej.szulik and 
@berker.peksag

Description:-
This patch adds a new table "pull_request" which is used to save GitHub PR URLs.
URL can be added manually using "GitHub PR" field on issue's page.

---

GitHub PR URL will also be added automatically in two ways - for that, you can 
have a look at issue589 and issue600

___
PSF Meta Tracker <metatrac...@psf.upfronthosting.co.za>
<http://psf.upfronthosting.co.za/roundup/meta/issue586>
___diff --git a/detectors/pull_request.py b/detectors/pull_request.py
new file mode 100644
index 000..6a206e5
--- /dev/null
+++ b/detectors/pull_request.py
@@ -0,0 +1,35 @@
+# Auditor for GitHub URLs
+# Check if it is a valid GitHub Pull Request URL and extract PR number
+
+import re
+import urlparse
+
+
+def validate_github_url(db, cl, nodeid, newvalues):
+url = newvalues.get('url', '')
+if url == '':
+return
+parsed_url = urlparse.urlparse(url)
+if parsed_url.scheme == '':
+url = 'https://' + url
+parsed_url = urlparse.urlparse(url)
+if parsed_url.scheme not in ('http', 'https'):
+raise ValueError("Invalid URL scheme in GitHub PR")
+if 'github.com' not in parsed_url.netloc or 'pull' not in parsed_url.path:
+raise ValueError("Invalid GitHub PR")
+newvalues['url'] = parsed_url.geturl()
+regex = re.match(".*/pull/(\d+)", newvalues['url'])
+if regex and len(regex.groups()) == 1:
+pr_no = regex.groups()[0]
+try:
+db.pull_request.lookup(pr_no)
+raise ValueError("GitHub PR already added to an issue")
+except KeyError:
+newvalues['pr_no'] = pr_no
+else:
+raise ValueError("Invalid GitHub PR")
+
+
+def init(db):
+db.pull_request.audit('create', validate_github_url)
+db.pull_request.audit('set', validate_github_url)
diff --git a/html/issue.item.html b/html/issue.item.html
index ddc4ec3..17eecd1 100644
--- a/html/issue.item.html
+++ b/html/issue.item.html
@@ -220,6 +220,14 @@
  
 
 
+
+ GitHub PR:
+ 
+  
+  
+ 
+
+
 
 
 
@@ -273,6 +281,43 @@
  
 
 
+
+ GitHub Pull 
Requests
+ 
+  Link
+  Author
+  Date
+  Edit
+  Remove
+ 
+ 
+  
+   
+GitHub PR link
+   
+  
+  
+   creator's name
+  
+  
+   creation date
+  
+  
+edit
+  
+  
+
+ 
+ 
+ 
+
+  
+ 
+
+
 
diff --git a/schema.py b/schema.py
index d91bf7b..c125a5f 100644
--- a/schema.py
+++ b/schema.py
@@ -173,6 +173,12 @@ hgrepo = Class(db, "hgrepo",
patchbranch=String(),
)
 
+pull_request = Class(db, "pull_request",
+ url=String(),
+ pr_no=String(),)
+
+pull_request.setkey("pr_no")
+
 # IssueClass automatically gets these properties in addition to the Class ones:
 #   title = String()
 #   messages = Multilink("msg")
@@ -194,7 +200,8 @@ issue = IssueClass(db, "issue",
stage=Link('stage'),
nosy_count=Number(),
message_count=Number(),
-   hgrepos=Multilink('hgrepo'))
+   hgrepos=Multilink('hgrepo'),
+   pull_requests=Multilink('pull_request'))
 
 #
 # TRACKER SECURITY SETTINGS
@@ -222,7 +229,7 @@ for r in 'User', 'Developer', 'Coordinator':
 
 for cl in ('issue_type', 'severity', 'component',
'version', 'priority', 'stage', 'status', 'resolution',
-   'issue', 'keyword', 'hgrepo'):
+   'issue', 'keyword', 'hgrepo', 'pull_request'):
 db.security.addPermissionToRole('User', 'View', cl)
 db.security.addPermissionToRole('Anonymous', 'View', cl)
 
@@ -233,6 +240,13 @@ p = db.security.addPermission(name='Edit', klass='hgrepo', 
check=may_edit_hgrepo
   properties=['url', 'patchbranch'])
 db.security.addPermissionToRole('User', p)
 
+def may_edit_github_url(db, userid, itemid):
+return userid == db.pull_request.get(itemid, "creator")
+db.security.addPermissionToRole('User', 'Create', 'pull_request')
+p = db.security.addPermission(name='Edit', klass='pull_request',
+  check=may_edit_github_url, properties=['url'])
+db.security.addPermissionToRole('User', p)
+
 class may_view_spam:
 def __init__(self, klassname):
 self.klassname = klassname
@@ -292,7 +306,7 @@ p = db.security.addPermission(name='Create', klass='issue',
   properties=('title', 'type',
   'components', 'versions',
   'severity',
-  'messages', 'files', 'nosy', 
'hgrepos'),
+ 

[Tracker-discuss] [issue586] Add GitHub Pull Request URL on issue page

2016-07-13 Thread Anish Shah

Anish Shah added the comment:

@berker.peksag

Thank you for the review. I will make those changes.

> Also, I'm not fan of such a manual work. I would prefer to have a JSON 
> endpoint > which queries open pull requests on python/cpython and match if 
> the title of a > pull request contains the issue number.

This is the first patch as a part of my GSoC project. You can check issue589 
where I'm using GitHub webhooks to link issues automatically.

___
PSF Meta Tracker <metatrac...@psf.upfronthosting.co.za>
<http://psf.upfronthosting.co.za/roundup/meta/issue586>
___
___
Tracker-discuss mailing list
Tracker-discuss@python.org
https://mail.python.org/mailman/listinfo/tracker-discuss
Code of Conduct: https://www.python.org/psf/codeofconduct/


[Tracker-discuss] [issue600] Convert patches to GitHub Pull Request

2016-06-19 Thread Anish Shah

New submission from Anish Shah:

This is an initial patch to convert .patch/.diff files to GitHub Pull Requests.

--
files: patch-to-pr.diff
messages: 3055
nosy: anish.shah, maciej.szulik
priority: feature
status: in-progress
title: Convert patches to GitHub Pull Request

___
PSF Meta Tracker <metatrac...@psf.upfronthosting.co.za>
<http://psf.upfronthosting.co.za/roundup/meta/issue600>
___diff --git a/detectors/patches.py b/detectors/patches.py
index 18d3db4..7a27d5f 100644
--- a/detectors/patches.py
+++ b/detectors/patches.py
@@ -5,16 +5,83 @@
 
 import posixpath
 import identify_patch
+import os
+import subprocess
+import string
+import random
+import json
+import requests
 
 patchtypes = ('.diff', '.patch')
 sourcetypes = ('.diff', '.patch', '.py')
 
+def create_pull_request(db, head, base, issue_id, issue_title):
+endpoint = 'https://api.github.com/repos/AnishShah/cpython/pulls'
+access_token = os.environ['ACCESS_TOKEN']
+headers = {'Authorization': 'token {}'.format(access_token)}
+data = json.dumps({
+"title": "{}".format(issue_title),
+"body": "fixes issue {}".format(issue_id),
+"base": base, "head": head})
+response = requests.post(endpoint, headers=headers, data=data)
+if not response.ok:
+raise Exception('Error generating pull request')
+else:
+response_body = response.json()
+url = response_body['html_url']
+state = response_body['state']
+pr_id = db.github_pullrequest_url.create(url=url, state=state)
+issue_pr = db.issue.get(issue_id, 'github_pullrequest_urls')
+issue_pr.append(pr_id)
+db.issue.set(issue_id, github_pullrequest_urls=issue_pr)
+db.commit()
+
+def git_command(command, path):
+process = subprocess.Popen(command, cwd=path, shell=True,
+   stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+out, err = process.communicate()
+# err takes stdout
+# if err:
+# raise Exception(err)
+
+def git_workflow(db, issue_id, file_id):
+path = os.environ['GIT_PATH']
+versions = map(lambda id: (db.version.get(id, 'name'), db.version.get(id, 
'order')),
+   db.issue.get(issue_id, 'versions'))
+title = db.issue.get(issue_id, 'title')
+commit_msg = 'Fixes issue {} : {}'.format(issue_id, title)
+if len(versions) == 0:
+parent_branch = "master"
+else:
+version = versions.pop()
+if version[1] == 1:
+parent_branch = "master"
+else:
+parent_branch = version[0].split()[1]
+branch_name = ''.join([random.choice(string.ascii_letters) for i in 
range(random.choice(range(10, 20)))])
+filename = db.file.get(file_id, 'name')
+content = db.file.get(file_id, 'content')
+fp = open(os.path.join(path, filename), 'wb')
+fp.write(content)
+fp.close()
+git_command("git checkout {}".format(parent_branch), path)
+git_command("git checkout -b {}".format(branch_name), path)
+git_command("git apply {}".format(filename), path)
+git_command("git add -A", path)
+git_command("git commit -m \"{}\"".format(commit_msg), path)
+git_command("git push origin {}".format(branch_name), path)
+git_command("git checkout {}".format(parent_branch), path)
+git_command("git branch -D {}".format(branch_name), path)
+create_pull_request(db, branch_name, parent_branch, issue_id, title)
+
+
 def ispatch(file, types):
 return posixpath.splitext(file)[1] in types
 
 def patches_text_plain(db, cl, nodeid, newvalues):
 if ispatch(newvalues['name'], sourcetypes):
 newvalues['type'] = 'text/plain'
+# git_workflow(newvalues)
 
 def patches_keyword(db, cl, nodeid, newvalues):
 # Check whether there are any new files
@@ -26,6 +93,7 @@ def patches_keyword(db, cl, nodeid, newvalues):
 for fileid in newfiles:
 if ispatch(db.file.get(fileid, 'name'), patchtypes):
 newpatch = True
+git_workflow(db, nodeid, fileid)
 break
 if newpatch:
 # Add the patch keyword if its not already there
diff --git a/initial_data.py b/initial_data.py
index dc0ed4f..a9eee3a 100644
--- a/initial_data.py
+++ b/initial_data.py
@@ -49,13 +49,12 @@ component.create(name="Windows", order="18")
 component.create(name="XML", order="19")
 
 version = db.getclass('version')
-version.create(name='Python 3.1', order='1')
-version.create(name='Python 3.0', order='2')
-version.create(name='Python 2.7', order='3')
-version.create(name='Python 2.6', order='4')
-version.create(name='Python 2.5', order='5')
-version.create(name='Python 2.4', order='6')
-