##// END OF EJS Templates
Merge pull request #13212 from python-pitfalls/master...
Merge pull request #13212 from python-pitfalls/master removed a name shadowing pitfall

File last commit:

r24132:ddfa1ba0
r26942:65b80ee4 merge
Show More
backport_pr.py
192 lines | 5.6 KiB | text/x-python | PythonLexer
MinRK
shebang backport_pr
r8347 #!/usr/bin/env python
MinRK
add backport_pr to tools...
r8346 """
Backport pull requests to a particular branch.
Jonathan Frederic
Add repo support
r21985 Usage: backport_pr.py [org/repository] branch [PR] [PR2]
MinRK
add backport_pr to tools...
r8346
e.g.:
MinRK
allow backporting several PRs at once
r16761 python tools/backport_pr.py 0.13.1 123 155
MinRK
add backport_pr to tools...
r8346
Jonathan Frederic
Add repo support
r21985 to backport PRs #123 and #155 onto branch 0.13.1
MinRK
add backport_pr to tools...
r8346
MinRK
add ability to check what PRs should be backported in backport_pr...
r12424 or
MinRK
use milestones to indicate backport
r16167 python tools/backport_pr.py 2.1
MinRK
add ability to check what PRs should be backported in backport_pr...
r12424
MinRK
use milestones to indicate backport
r16167 to see what PRs are marked for backport with milestone=2.1 that have yet to be applied
Jonathan Frederic
Add repo support
r21985 to branch 2.x
or
python tools/backport_pr.py jupyter/notebook 0.13.1 123 155
to backport PRs #123 and #155 of the `jupyter/notebook` repo onto branch 0.13.1
of that repo.
MinRK
add ability to check what PRs should be backported in backport_pr...
r12424
MinRK
add backport_pr to tools...
r8346 """
import os
MinRK
add ability to check what PRs should be backported in backport_pr...
r12424 import re
MinRK
add backport_pr to tools...
r8346 import sys
MinRK
add ability to check what PRs should be backported in backport_pr...
r12424
MinRK
add backport_pr to tools...
r8346 from subprocess import Popen, PIPE, check_call, check_output
Thomas Kluyver
Start making backport_pr work on Python 3
r16178 try:
from urllib.request import urlopen
except:
MinRK
allow backporting several PRs at once
r16761 from urllib import urlopen
MinRK
add backport_pr to tools...
r8346
MinRK
add ability to check what PRs should be backported in backport_pr...
r12424 from gh_api import (
get_issues_list,
get_pull_request,
get_pull_request_files,
is_pull_request,
Skipper Seabold
Allow checking for backports via milestone
r13169 get_milestone_id,
MinRK
add ability to check what PRs should be backported in backport_pr...
r12424 )
MinRK
add backport_pr to tools...
r8346
def find_rejects(root='.'):
for dirname, dirs, files in os.walk(root):
for fname in files:
if fname.endswith('.rej'):
yield os.path.join(dirname, fname)
def get_current_branch():
branches = check_output(['git', 'branch'])
for branch in branches.splitlines():
Thomas Kluyver
Start making backport_pr work on Python 3
r16178 if branch.startswith(b'*'):
return branch[1:].strip().decode('utf-8')
MinRK
add backport_pr to tools...
r8346
def backport_pr(branch, num, project='ipython/ipython'):
current_branch = get_current_branch()
if branch != current_branch:
check_call(['git', 'checkout', branch])
Thomas Kluyver
Update target branch before backporting PR
r12276 check_call(['git', 'pull'])
MinRK
get files list in backport_pr...
r12129 pr = get_pull_request(project, num, auth=True)
files = get_pull_request_files(project, num, auth=True)
MinRK
add backport_pr to tools...
r8346 patch_url = pr['patch_url']
title = pr['title']
description = pr['body']
fname = "PR%i.patch" % num
if os.path.exists(fname):
print("using patch from {fname}".format(**locals()))
Min RK
[py3] backport_pr: read patch as bytes...
r18786 with open(fname, 'rb') as f:
MinRK
add backport_pr to tools...
r8346 patch = f.read()
else:
req = urlopen(patch_url)
patch = req.read()
Skipper Seabold
Allow checking for backports via milestone
r13169
MinRK
truncate PR description in backported git msg to five lines...
r16762 lines = description.splitlines()
if len(lines) > 5:
lines = lines[:5] + ['...']
description = '\n'.join(lines)
MinRK
add backport_pr to tools...
r8346 msg = "Backport PR #%i: %s" % (num, title) + '\n\n' + description
check = Popen(['git', 'apply', '--check', '--verbose'], stdin=PIPE)
a,b = check.communicate(patch)
Skipper Seabold
Allow checking for backports via milestone
r13169
MinRK
add backport_pr to tools...
r8346 if check.returncode:
print("patch did not apply, saving to {fname}".format(**locals()))
print("edit {fname} until `cat {fname} | git apply --check` succeeds".format(**locals()))
print("then run tools/backport_pr.py {num} again".format(**locals()))
if not os.path.exists(fname):
with open(fname, 'wb') as f:
f.write(patch)
return 1
Skipper Seabold
Allow checking for backports via milestone
r13169
MinRK
add backport_pr to tools...
r8346 p = Popen(['git', 'apply'], stdin=PIPE)
a,b = p.communicate(patch)
Skipper Seabold
Allow checking for backports via milestone
r13169
MinRK
get files list in backport_pr...
r12129 filenames = [ f['filename'] for f in files ]
MinRK
add backport_pr to tools...
r8346
MinRK
use check_call for git add and commit...
r12341 check_call(['git', 'add'] + filenames)
Skipper Seabold
Allow checking for backports via milestone
r13169
MinRK
use check_call for git add and commit...
r12341 check_call(['git', 'commit', '-m', msg])
Skipper Seabold
Allow checking for backports via milestone
r13169
MinRK
use check_call for git add and commit...
r12341 print("PR #%i applied, with msg:" % num)
print()
print(msg)
print()
Skipper Seabold
Allow checking for backports via milestone
r13169
MinRK
add backport_pr to tools...
r8346 if branch != current_branch:
check_call(['git', 'checkout', current_branch])
Skipper Seabold
Allow checking for backports via milestone
r13169
MinRK
add backport_pr to tools...
r8346 return 0
Min RK
update already-backported search pattern...
r20874 backport_re = re.compile(r"(?:[Bb]ackport|[Mm]erge).*#(\d+)")
MinRK
add ability to check what PRs should be backported in backport_pr...
r12424
def already_backported(branch, since_tag=None):
"""return set of PRs that have been backported already"""
if since_tag is None:
since_tag = check_output(['git','describe', branch, '--abbrev=0']).decode('utf8').strip()
cmd = ['git', 'log', '%s..%s' % (since_tag, branch), '--oneline']
lines = check_output(cmd).decode('utf8')
return set(int(num) for num in backport_re.findall(lines))
Jonathan Frederic
Make should_backport work on other projects
r21984 def should_backport(labels=None, milestone=None, project='ipython/ipython'):
MinRK
add ability to check what PRs should be backported in backport_pr...
r12424 """return set of PRs marked for backport"""
Skipper Seabold
Allow checking for backports via milestone
r13169 if labels is None and milestone is None:
raise ValueError("Specify one of labels or milestone.")
elif labels is not None and milestone is not None:
raise ValueError("Specify only one of labels or milestone.")
if labels is not None:
Jonathan Frederic
Make should_backport work on other projects
r21984 issues = get_issues_list(project,
Skipper Seabold
Allow checking for backports via milestone
r13169 labels=labels,
state='closed',
auth=True,
)
else:
Jonathan Frederic
Make should_backport work on other projects
r21984 milestone_id = get_milestone_id(project, milestone,
Skipper Seabold
Allow checking for backports via milestone
r13169 auth=True)
Jonathan Frederic
Make should_backport work on other projects
r21984 issues = get_issues_list(project,
Skipper Seabold
Allow checking for backports via milestone
r13169 milestone=milestone_id,
state='closed',
auth=True,
)
MinRK
add ability to check what PRs should be backported in backport_pr...
r12424 should_backport = set()
for issue in issues:
if not is_pull_request(issue):
continue
Jonathan Frederic
Make should_backport work on other projects
r21984 pr = get_pull_request(project, issue['number'],
Skipper Seabold
Allow checking for backports via milestone
r13169 auth=True)
MinRK
add ability to check what PRs should be backported in backport_pr...
r12424 if not pr['merged']:
print ("Marked PR closed without merge: %i" % pr['number'])
continue
MinRK
don't suggest backporting PRs against refs other than master
r16673 if pr['base']['ref'] != 'master':
continue
MinRK
add ability to check what PRs should be backported in backport_pr...
r12424 should_backport.add(pr['number'])
return should_backport
MinRK
add backport_pr to tools...
r8346 if __name__ == '__main__':
Jonathan Frederic
Add repo support
r21985 project = 'ipython/ipython'
Matthias Bussonnier
recommend GhPro as a replacemetn for custom tools
r22897
luz.paz
Misc. typos fixes...
r24132 print("DEPRECATE: backport_pr.py is deprecated and it is now recommended"
Matthias Bussonnier
recommend GhPro as a replacemetn for custom tools
r22897 "to install `ghpro` from PyPI.", file=sys.stderr)
Jonathan Frederic
Add repo support
r21985 args = list(sys.argv)
if len(args) >= 2:
if '/' in args[1]:
project = args[1]
del args[1]
if len(args) < 2:
MinRK
add backport_pr to tools...
r8346 print(__doc__)
sys.exit(1)
Skipper Seabold
Allow checking for backports via milestone
r13169
Jonathan Frederic
Add repo support
r21985 if len(args) < 3:
milestone = args[1]
MinRK
use milestones to indicate backport
r16167 branch = milestone.split('.')[0] + '.x'
MinRK
add ability to check what PRs should be backported in backport_pr...
r12424 already = already_backported(branch)
Jonathan Frederic
Add repo support
r21985 should = should_backport(milestone=milestone, project=project)
MinRK
add ability to check what PRs should be backported in backport_pr...
r12424 print ("The following PRs should be backported:")
MinRK
sort backport PRs
r13952 for pr in sorted(should.difference(already)):
MinRK
add ability to check what PRs should be backported in backport_pr...
r12424 print (pr)
sys.exit(0)
Jonathan Frederic
Add repo support
r21985
for prno in map(int, args[2:]):
MinRK
allow backporting several PRs at once
r16761 print("Backporting PR #%i" % prno)
Jonathan Frederic
Add repo support
r21985 rc = backport_pr(args[1], prno, project=project)
MinRK
allow backporting several PRs at once
r16761 if rc:
print("Backporting PR #%i failed" % prno)
sys.exit(rc)