##// 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:

r43824:cf5eaf24 default
r44689:e960c30d default
Show More
inno.py
163 lines | 4.3 KiB | text/x-python | PythonLexer
Gregory Szorc
packaging: move Inno Setup core logic into a module...
r42077 # inno.py - Inno Setup functionality.
#
# Copyright 2019 Gregory Szorc <gregory.szorc@gmail.com>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
# no-check-code because Python 3 native.
import os
import pathlib
import shutil
import subprocess
Gregory Szorc
packaging: process Inno Setup files with Jinja2...
r43915 import jinja2
Gregory Szorc
packaging: stage installed files for Inno...
r43916 from .py2exe import (
build_py2exe,
stage_install,
)
Gregory Szorc
packaging: always pass VERSION into Inno invocation...
r43918 from .util import (
find_vc_runtime_files,
read_version_py,
)
Gregory Szorc
packaging: move Inno Setup core logic into a module...
r42077
Gregory Szorc
setup: configure py2exe config via environment variables...
r42082 EXTRA_PACKAGES = {
'dulwich',
'keyring',
'pygments',
'win32ctypes',
}
Gregory Szorc
packaging: stage installed files for Inno...
r43916 PACKAGE_FILES_METADATA = {
'ReadMe.html': 'Flags: isreadme',
}
Gregory Szorc
setup: configure py2exe config via environment variables...
r42082
Augie Fackler
formatting: blacken the codebase...
r43346 def build(
source_dir: pathlib.Path,
build_dir: pathlib.Path,
python_exe: pathlib.Path,
iscc_exe: pathlib.Path,
version=None,
):
Gregory Szorc
packaging: move Inno Setup core logic into a module...
r42077 """Build the Inno installer.
Build files will be placed in ``build_dir``.
py2exe's setup.py doesn't use setuptools. It doesn't have modern logic
for finding the Python 2.7 toolchain. So, we require the environment
to already be configured with an active toolchain.
"""
if not iscc_exe.exists():
raise Exception('%s does not exist' % iscc_exe)
Gregory Szorc
packaging: extract py2exe functionality to own module...
r42081 vc_x64 = r'\x64' in os.environ.get('LIB', '')
Gregory Szorc
packaging: install and run Inno files in a build directory...
r43914 arch = 'x64' if vc_x64 else 'x86'
inno_source_dir = source_dir / 'contrib' / 'packaging' / 'inno'
inno_build_dir = build_dir / ('inno-%s' % arch)
Gregory Szorc
packaging: stage installed files for Inno...
r43916 staging_dir = inno_build_dir / 'stage'
Gregory Szorc
packaging: move Inno Setup core logic into a module...
r42077
Augie Fackler
formatting: blacken the codebase...
r43346 requirements_txt = (
source_dir / 'contrib' / 'packaging' / 'inno' / 'requirements.txt'
)
Gregory Szorc
packaging: move Inno Setup core logic into a module...
r42077
Gregory Szorc
packaging: install and run Inno files in a build directory...
r43914 inno_build_dir.mkdir(parents=True, exist_ok=True)
Augie Fackler
formatting: blacken the codebase...
r43346 build_py2exe(
source_dir,
build_dir,
python_exe,
'inno',
requirements_txt,
extra_packages=EXTRA_PACKAGES,
)
Gregory Szorc
packaging: move Inno Setup core logic into a module...
r42077
Gregory Szorc
packaging: stage installed files for Inno...
r43916 # Purge the staging directory for every build so packaging is
# pristine.
if staging_dir.exists():
print('purging %s' % staging_dir)
shutil.rmtree(staging_dir)
# Now assemble all the packaged files into the staging directory.
stage_install(source_dir, staging_dir)
Gregory Szorc
packaging: don't use temporary directory...
r42079 # hg.exe depends on VC9 runtime DLLs. Copy those into place.
for f in find_vc_runtime_files(vc_x64):
if f.name.endswith('.manifest'):
basename = 'Microsoft.VC90.CRT.manifest'
else:
basename = f.name
Gregory Szorc
packaging: move Inno Setup core logic into a module...
r42077
Gregory Szorc
packaging: stage installed files for Inno...
r43916 dest_path = staging_dir / basename
Gregory Szorc
packaging: move Inno Setup core logic into a module...
r42077
Gregory Szorc
packaging: don't use temporary directory...
r42079 print('copying %s to %s' % (f, dest_path))
shutil.copyfile(f, dest_path)
Gregory Szorc
packaging: move Inno Setup core logic into a module...
r42077
Gregory Szorc
packaging: stage installed files for Inno...
r43916 # The final package layout is simply a mirror of the staging directory.
package_files = []
for root, dirs, files in os.walk(staging_dir):
dirs.sort()
root = pathlib.Path(root)
for f in sorted(files):
full = root / f
rel = full.relative_to(staging_dir)
if str(rel.parent) == '.':
dest_dir = '{app}'
else:
dest_dir = '{app}\\%s' % rel.parent
package_files.append(
{
'source': rel,
'dest_dir': dest_dir,
'metadata': PACKAGE_FILES_METADATA.get(str(rel), None),
}
)
Gregory Szorc
packaging: don't use temporary directory...
r42079 print('creating installer')
Gregory Szorc
packaging: process Inno Setup files with Jinja2...
r43915 # Install Inno files by rendering a template.
jinja_env = jinja2.Environment(
loader=jinja2.FileSystemLoader(str(inno_source_dir)),
# Need to change these to prevent conflict with Inno Setup.
comment_start_string='{##',
comment_end_string='##}',
)
try:
template = jinja_env.get_template('mercurial.iss')
except jinja2.TemplateSyntaxError as e:
raise Exception(
'template syntax error at %s:%d: %s'
% (e.name, e.lineno, e.message,)
)
Gregory Szorc
packaging: stage installed files for Inno...
r43916 content = template.render(package_files=package_files)
Gregory Szorc
packaging: process Inno Setup files with Jinja2...
r43915
with (inno_build_dir / 'mercurial.iss').open('w', encoding='utf-8') as fh:
fh.write(content)
Gregory Szorc
packaging: install and run Inno files in a build directory...
r43914
Gregory Szorc
packaging: stage installed files for Inno...
r43916 # Copy additional files used by Inno.
for p in ('mercurial.ico', 'postinstall.txt'):
shutil.copyfile(
source_dir / 'contrib' / 'win32' / p, inno_build_dir / p
)
Gregory Szorc
packaging: don't use temporary directory...
r42079 args = [str(iscc_exe)]
Gregory Szorc
packaging: move Inno Setup core logic into a module...
r42077
Gregory Szorc
packaging: don't use temporary directory...
r42079 if vc_x64:
args.append('/dARCH=x64')
Gregory Szorc
packaging: move Inno Setup core logic into a module...
r42077
Gregory Szorc
packaging: always pass VERSION into Inno invocation...
r43918 if not version:
version = read_version_py(source_dir)
args.append('/dVERSION=%s' % version)
Gregory Szorc
packaging: move Inno Setup core logic into a module...
r42077
Gregory Szorc
packaging: don't use temporary directory...
r42079 args.append('/Odist')
Gregory Szorc
packaging: install and run Inno files in a build directory...
r43914 args.append(str(inno_build_dir / 'mercurial.iss'))
Gregory Szorc
packaging: move Inno Setup core logic into a module...
r42077
Gregory Szorc
packaging: don't use temporary directory...
r42079 subprocess.run(args, cwd=str(source_dir), check=True)