##// END OF EJS Templates
rust-cpython: mark all PyLeaked methods as unsafe...
rust-cpython: mark all PyLeaked methods as unsafe Unfortunately, these methods can be abused to obtain the inner 'static reference. The simplest (pseudo-code) example is: let leaked: PyLeaked<&'static _> = shared.leak_immutable(); let static_ref: &'static _ = &*leaked.try_borrow(py)?; // PyLeakedRef::deref() tries to bound the lifetime to itself, but // the underlying data is a &'static reference, so the returned // reference can be &'static. This problem can be easily fixed by coercing the lifetime, but there are many other ways to achieve that, and there wouldn't be a generic solution: let leaked: PyLeaked<&'static [_]> = shared.leak_immutable(); let leaked_iter: PyLeaked<slice::Iter<'static, _>> = unsafe { leaked.map(|v| v.iter()) }; let static_slice: &'static [_] = leaked_iter.try_borrow(py)?.as_slice(); So basically I failed to design the safe borrowing interface. Maybe we'll instead have to add much more restricted interface on top of the unsafe PyLeaked methods? For instance, Iterator::next() could be implemented if its Item type is not &'a (where 'a may be cheated.) Anyway, this seems not an easy issue, so it's probably better to leave the current interface as unsafe, and get broader comments while upstreaming this feature.

File last commit:

r43812:2fe6121c default
r44689:e960c30d default
Show More
python3-ratchet.py
161 lines | 4.5 KiB | text/x-python | PythonLexer
/ contrib / python3-ratchet.py
Augie Fackler
contrib: add a ratchet for tests in Python 3...
r32855 # Copyright 2012 Facebook
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
"""Find tests that newly pass under Python 3.
The approach is simple: we maintain a whitelist of Python 3 passing
tests in the repository, and periodically run all the /other/ tests
and look for new passes. Any newly passing tests get automatically
added to the whitelist.
You probably want to run it like this:
$ cd tests
$ python3 ../contrib/python3-ratchet.py \
> --working-tests=../contrib/python3-whitelist
"""
from __future__ import print_function
from __future__ import absolute_import
import argparse
import json
import os
import subprocess
import sys
_hgenv = dict(os.environ)
Augie Fackler
formatting: blacken the codebase...
r43346 _hgenv.update(
{'HGPLAIN': '1',}
)
Augie Fackler
contrib: add a ratchet for tests in Python 3...
r32855
_HG_FIRST_CHANGE = '9117c6561b0bd7792fa13b50d28239d51b78e51f'
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
contrib: add a ratchet for tests in Python 3...
r32855 def _runhg(*args):
return subprocess.check_output(args, env=_hgenv)
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
contrib: add a ratchet for tests in Python 3...
r32855 def _is_hg_repo(path):
Augie Fackler
formatting: blacken the codebase...
r43346 return (
_runhg('hg', 'log', '-R', path, '-r0', '--template={node}').strip()
== _HG_FIRST_CHANGE
)
Augie Fackler
contrib: add a ratchet for tests in Python 3...
r32855
def _py3default():
if sys.version_info[0] >= 3:
return sys.executable
return 'python3'
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
contrib: add a ratchet for tests in Python 3...
r32855 def main(argv=()):
p = argparse.ArgumentParser()
Augie Fackler
formatting: blacken the codebase...
r43346 p.add_argument(
'--working-tests', help='List of tests that already work in Python 3.'
)
p.add_argument(
'--commit-to-repo',
help='If set, commit newly fixed tests to the given repo',
)
p.add_argument(
'-j',
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 default=os.sysconf('SC_NPROCESSORS_ONLN'),
Augie Fackler
formatting: blacken the codebase...
r43346 type=int,
help='Number of parallel tests to run.',
)
p.add_argument(
'--python3',
default=_py3default(),
help='python3 interpreter to use for test run',
)
p.add_argument(
'--commit-user',
default='python3-ratchet@mercurial-scm.org',
help='Username to specify when committing to a repo.',
)
Augie Fackler
contrib: add a ratchet for tests in Python 3...
r32855 opts = p.parse_args(argv)
if opts.commit_to_repo:
if not _is_hg_repo(opts.commit_to_repo):
print('abort: specified repository is not the hg repository')
sys.exit(1)
if not opts.working_tests or not os.path.isfile(opts.working_tests):
Augie Fackler
formatting: blacken the codebase...
r43346 print(
'abort: --working-tests must exist and be a file (got %r)'
% opts.working_tests
)
Augie Fackler
contrib: add a ratchet for tests in Python 3...
r32855 sys.exit(1)
elif opts.commit_to_repo:
root = _runhg('hg', 'root').strip()
if not opts.working_tests.startswith(root):
Augie Fackler
formatting: blacken the codebase...
r43346 print(
'abort: if --commit-to-repo is given, '
'--working-tests must be from that repo'
)
Augie Fackler
contrib: add a ratchet for tests in Python 3...
r32855 sys.exit(1)
try:
Augie Fackler
formatting: blacken the codebase...
r43346 subprocess.check_call(
[
opts.python3,
'-c',
'import sys ; '
'assert ((3, 5) <= sys.version_info < (3, 6) '
'or sys.version_info >= (3, 6, 2))',
]
)
Augie Fackler
contrib: add a ratchet for tests in Python 3...
r32855 except subprocess.CalledProcessError:
Augie Fackler
formatting: blacken the codebase...
r43346 print(
'warning: Python 3.6.0 and 3.6.1 have '
'a bug which breaks Mercurial'
)
Augie Fackler
contrib: add a ratchet for tests in Python 3...
r32855 print('(see https://bugs.python.org/issue29714 for details)')
Kevin Bullock
py3: bail on ratcheting tests forward on 3.6.0 and 3.6.1
r36607 sys.exit(1)
Augie Fackler
contrib: add a ratchet for tests in Python 3...
r32855
Augie Fackler
formatting: blacken the codebase...
r43346 rt = subprocess.Popen(
[
opts.python3,
'run-tests.py',
'-j',
str(opts.j),
'--blacklist',
opts.working_tests,
'--json',
]
)
Augie Fackler
contrib: add a ratchet for tests in Python 3...
r32855 rt.wait()
with open('report.json') as f:
data = f.read()
report = json.loads(data.split('=', 1)[1])
newpass = set()
for test, result in report.items():
if result['result'] != 'success':
continue
# A new passing test! Huzzah!
newpass.add(test)
if newpass:
# We already validated the repo, so we can just dive right in
# and commit.
if opts.commit_to_repo:
print(len(newpass), 'new passing tests on Python 3!')
with open(opts.working_tests) as f:
oldpass = {l for l in f.read().splitlines() if l}
with open(opts.working_tests, 'w') as f:
for p in sorted(oldpass | newpass):
f.write('%s\n' % p)
Augie Fackler
formatting: blacken the codebase...
r43346 _runhg(
'hg',
'commit',
'-R',
opts.commit_to_repo,
'--user',
opts.commit_user,
'--message',
'python3: expand list of passing tests',
)
Augie Fackler
contrib: add a ratchet for tests in Python 3...
r32855 else:
print('Newly passing tests:', '\n'.join(sorted(newpass)))
sys.exit(2)
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
contrib: add a ratchet for tests in Python 3...
r32855 if __name__ == '__main__':
main(sys.argv[1:])