Maciej Szulik added the comment:
Apparently I can't leave title set to none, I had to explicitly set it to empty
if none is set.
_______________________________________________________
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
--- /dev/null
+++ b/detectors/pull_request.py
@@ -0,0 +1,55 @@
+# Auditor for GitHub URLs
+# Check if it is a valid GitHub Pull Request URL and extract PR number
+
+import re
+import urlparse
+
+
+def validate_pull_requests(db, cl, nodeid, newvalues):
+ newprs = set(newvalues.get('pull_requests',()))
+ oldprs = set()
+ if nodeid:
+ oldprs = set(db.issue.get(nodeid, 'pull_requests'))
+ newprs -= oldprs
+ newurl = ''
+ for prid in newprs:
+ newurl = parse_url(db.pull_request.get(prid, 'url'))
+ if newurl != '':
+ for prid in oldprs:
+ if newurl == db.pull_request.get(prid, 'url'):
+ raise ValueError("GitHub PR already added to issue")
+
+def validate_url(db, cl, nodeid, newvalues):
+ try:
+ newurl = parse_url(newvalues['url'])
+ if newurl != '':
+ newvalues['url'] = newurl
+ except KeyError:
+ pass
+ try:
+ newvalues['title']
+ except KeyError:
+ newvalues['title'] = ''
+
+def parse_url(url):
+ if url == '':
+ return
+ # TODO: transform following forms:
+ # - username/repo#prno
+ # - repo/#prno
+ 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")
+ return parsed_url.geturl().strip('/')
+
+
+def init(db):
+ db.issue.audit('create', validate_pull_requests)
+ db.issue.audit('set', validate_pull_requests)
+ db.pull_request.audit('create', validate_url)
+ db.pull_request.audit('set', validate_url)
diff --git a/html/issue.item.html b/html/issue.item.html
--- a/html/issue.item.html
+++ b/html/issue.item.html
@@ -220,6 +220,14 @@
</td>
</tr>
+<tr tal:condition="context/is_edit_ok">
+ <th><tal:block>GitHub PR</tal:block>:</th>
+ <td colspan="3">
+ <input type="hidden" name="@link@pull_requests" value="pull_request-1">
+ <input type="text" name="pull_request-1@url" size="50">
+ </td>
+</tr>
+
</table>
</fieldset>
<table class="form">
@@ -273,6 +281,31 @@
</tr>
</table>
+<table class="files" tal:condition="context/pull_requests">
+ <tr><th class="header" colspan="5">Pull Requests</th></tr>
+ <tr>
+ <th>URL</th>
+ <th>Linked</th>
+ <th>Edit</th>
+ </tr>
+ <tr tal:repeat="pull_request python:context.pull_requests.sorted('creation')">
+ <td>
+ <a tal:attributes="href pull_request/url; title pull_request/title"
+ tal:content="pull_request/url" target="_blank">
+ URL
+ </a>
+ </td>
+ <td>
+ <span tal:content="pull_request/creator">creator's name</span>,
+ <span tal:content="python:pull_request.creation.pretty('%Y-%m-%d
%H:%M')">creation date</span>
+ </td>
+ <td>
+ <a tal:condition="pull_request/is_edit_ok"
+ tal:attributes="href string:pull_request${pull_request/id}">edit</a>
+ </td>
+ </tr>
+</table>
+
<p tal:condition="python: context.id and not request.user.contrib_form and
any(file.creator.id == request.user.id for file in
context.files)"
id="contribform">
diff --git a/html/pull_request.item.html b/html/pull_request.item.html
new file mode 100644
--- /dev/null
+++ b/html/pull_request.item.html
@@ -0,0 +1,72 @@
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title" i18n:translate="">Pull Request - <span
+ i18n:name="tracker" tal:replace="config/TRACKER_NAME" /></title>
+<span metal:fill-slot="body_title" tal:omit-tag="python:1"
+ i18n:translate="">Pull Request</span>
+
+<td class="content" metal:fill-slot="content">
+
+<p tal:condition="python:not (context.is_view_ok()
+ or request.user.hasRole('Anonymous'))" i18n:translate="">
+ You are not allowed to view this page.</p>
+
+<p tal:condition="python:not context.is_view_ok()
+ and request.user.hasRole('Anonymous')" i18n:translate="">
+ Please login with your username and password.</p>
+
+<form method="POST" onSubmit="return submit_once()"
+ enctype="multipart/form-data" tal:condition="context/is_view_ok"
+ tal:attributes="action context/designator">
+
+<table class="form">
+ <tr>
+ <th i18n:translate="">URL</th>
+ <td tal:content="structure context/url/field"></td>
+ </tr>
+ <tr>
+ <th i18n:translate="">Title</th>
+ <td tal:content="structure context/title/field"></td>
+ </tr>
+
+ <tr tal:condition="python:context.is_edit_ok()">
+ <td>
+
+ <input type="hidden" name="@template" value="item">
+ <input type="hidden" name="@required" value="url">
+ <input type="hidden" name="@multilink"
+ tal:condition="python:request.form.has_key('@multilink')"
+ tal:attributes="value request/form/@multilink/value">
+ </td>
+ <td tal:content="structure context/submit">submit button here</td>
+ </tr>
+</table>
+</form>
+
+<p tal:condition="python:utils.sb_is_spam(context)" class="error-message">
+ File has been classified as spam.</p>
+
+<form tal:define="u_hasRole python:request.user.hasRole;
+ issueid_action
python:utils.issueid_and_action_from_class(context);
+ issueid python:'issue%s' % issueid_action[0];
+ action python:issueid_action[1]"
+ tal:condition="python:issueid and context.is_edit_ok()"
+ tal:attributes="action issueid" method="post">
+ <input type="hidden" name="@action" value="edit" />
+ <tal:block tal:condition="python: action == 'link'">
+ <input type="hidden" name="@remove@pull_requests"
tal:attributes="value context/id" />
+ <p>This PR is linked to <a tal:attributes="href issueid"
tal:content="issueid" />:
+ <input type="submit" value="Unlink" i18n:attributes="value"/></p>
+ </tal:block>
+ <tal:block tal:condition="python: action == 'unlink'">
+ <input type="hidden" name="@add@pull_requests" tal:attributes="value
context/id" />
+ <p>This PR has been unlinked from <a tal:attributes="href issueid"
tal:content="issueid" />:
+ <input type="submit" value="Restore" i18n:attributes="value"/></p>
+ </tal:block>
+</form>
+
+
+<tal:block tal:condition="context/id" tal:replace="structure context/history"
/>
+
+</td>
+
+</tal:block>
diff --git a/schema.py b/schema.py
--- a/schema.py
+++ b/schema.py
@@ -173,6 +173,11 @@
patchbranch=String(),
)
+pull_request = Class(db, "pull_request",
+ url=String(),
+ title=String(),
+ )
+
# IssueClass automatically gets these properties in addition to the Class ones:
# title = String()
# messages = Multilink("msg")
@@ -194,7 +199,8 @@
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 +228,7 @@
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 +239,13 @@
properties=['url', 'patchbranch'])
db.security.addPermissionToRole('User', p)
+def may_edit_pull_request(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_pull_request, properties=['url',
'title'])
+db.security.addPermissionToRole('User', p)
+
class may_view_spam:
def __init__(self, klassname):
self.klassname = klassname
@@ -292,7 +305,7 @@
properties=('title', 'type',
'components', 'versions',
'severity',
- 'messages', 'files', 'nosy',
'hgrepos'),
+ 'messages', 'files', 'nosy',
'hgrepos', 'pull_requests'),
description='User can report and discuss issues')
db.security.addPermissionToRole('User', p)
@@ -300,7 +313,7 @@
properties=('title', 'type',
'components', 'versions',
'severity',
- 'messages', 'files', 'nosy',
'hgrepos'),
+ 'messages', 'files', 'nosy',
'hgrepos', 'pull_requests'),
description='User can report and discuss issues')
db.security.addPermissionToRole('User', p)
@@ -335,7 +348,7 @@
##########################
for cl in ('issue_type', 'severity', 'component',
'version', 'priority', 'stage', 'status', 'resolution', 'issue',
- 'file', 'msg', 'hgrepo'):
+ 'file', 'msg', 'hgrepo', 'pull_request'):
db.security.addPermissionToRole('Coordinator', 'View', cl)
db.security.addPermissionToRole('Coordinator', 'Edit', cl)
db.security.addPermissionToRole('Coordinator', 'Create', cl)
_______________________________________________
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/