Implement Windows release builds in Azure Pipelines (GH-14065)

This commit is contained in:
Steve Dower 2019-06-14 08:29:20 -07:00 committed by GitHub
parent f0749da9a5
commit 21a92f8cda
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
46 changed files with 1692 additions and 167 deletions

View file

@ -17,12 +17,7 @@ from xml.etree import ElementTree as ET
from .constants import *
__all__ = []
def public(f):
__all__.append(f.__name__)
return f
__all__ = ["get_appx_layout"]
APPX_DATA = dict(
@ -166,9 +161,7 @@ REGISTRY = {
"Help": {
"Main Python Documentation": {
"_condition": lambda ns: ns.include_chm,
"": "[{{AppVPackageRoot}}]\\Doc\\{}".format(
PYTHON_CHM_NAME
),
"": "[{{AppVPackageRoot}}]\\Doc\\{}".format(PYTHON_CHM_NAME),
},
"Local Python Documentation": {
"_condition": lambda ns: ns.include_html_doc,
@ -239,31 +232,6 @@ def _fixup_sccd(ns, sccd, new_hash=None):
return sccd
@public
def get_appx_layout(ns):
if not ns.include_appxmanifest:
return
yield "AppxManifest.xml", ns.temp / "AppxManifest.xml"
yield "_resources.xml", ns.temp / "_resources.xml"
icons = ns.source / "PC" / "icons"
yield "_resources/pythonx44.png", icons / "pythonx44.png"
yield "_resources/pythonx44$targetsize-44_altform-unplated.png", icons / "pythonx44.png"
yield "_resources/pythonx50.png", icons / "pythonx50.png"
yield "_resources/pythonx50$targetsize-50_altform-unplated.png", icons / "pythonx50.png"
yield "_resources/pythonx150.png", icons / "pythonx150.png"
yield "_resources/pythonx150$targetsize-150_altform-unplated.png", icons / "pythonx150.png"
yield "_resources/pythonwx44.png", icons / "pythonwx44.png"
yield "_resources/pythonwx44$targetsize-44_altform-unplated.png", icons / "pythonwx44.png"
yield "_resources/pythonwx150.png", icons / "pythonwx150.png"
yield "_resources/pythonwx150$targetsize-150_altform-unplated.png", icons / "pythonwx150.png"
sccd = ns.source / SCCD_FILENAME
if sccd.is_file():
# This should only be set for side-loading purposes.
sccd = _fixup_sccd(ns, sccd, os.getenv("APPX_DATA_SHA256"))
yield sccd.name, sccd
def find_or_add(xml, element, attr=None, always_add=False):
if always_add:
e = None
@ -393,7 +361,6 @@ def disable_registry_virtualization(xml):
e = find_or_add(e, "rescap:Capability", ("Name", "unvirtualizedResources"))
@public
def get_appxmanifest(ns):
for k, v in APPXMANIFEST_NS.items():
ET.register_namespace(k, v)
@ -481,6 +448,29 @@ def get_appxmanifest(ns):
return buffer.getbuffer()
@public
def get_resources_xml(ns):
return RESOURCES_XML_TEMPLATE.encode("utf-8")
def get_appx_layout(ns):
if not ns.include_appxmanifest:
return
yield "AppxManifest.xml", ("AppxManifest.xml", get_appxmanifest(ns))
yield "_resources.xml", ("_resources.xml", get_resources_xml(ns))
icons = ns.source / "PC" / "icons"
yield "_resources/pythonx44.png", icons / "pythonx44.png"
yield "_resources/pythonx44$targetsize-44_altform-unplated.png", icons / "pythonx44.png"
yield "_resources/pythonx50.png", icons / "pythonx50.png"
yield "_resources/pythonx50$targetsize-50_altform-unplated.png", icons / "pythonx50.png"
yield "_resources/pythonx150.png", icons / "pythonx150.png"
yield "_resources/pythonx150$targetsize-150_altform-unplated.png", icons / "pythonx150.png"
yield "_resources/pythonwx44.png", icons / "pythonwx44.png"
yield "_resources/pythonwx44$targetsize-44_altform-unplated.png", icons / "pythonwx44.png"
yield "_resources/pythonwx150.png", icons / "pythonwx150.png"
yield "_resources/pythonwx150$targetsize-150_altform-unplated.png", icons / "pythonwx150.png"
sccd = ns.source / SCCD_FILENAME
if sccd.is_file():
# This should only be set for side-loading purposes.
sccd = _fixup_sccd(ns, sccd, os.getenv("APPX_DATA_SHA256"))
yield sccd.name, sccd

View file

@ -0,0 +1,66 @@
"""
Provides .props file.
"""
import os
from .constants import *
__all__ = ["get_nuspec_layout"]
PYTHON_NUSPEC_NAME = "python.nuspec"
NUSPEC_DATA = {
"PYTHON_TAG": VER_DOT,
"PYTHON_VERSION": os.getenv("PYTHON_NUSPEC_VERSION"),
"PYTHON_BITNESS": "64-bit" if IS_X64 else "32-bit",
"PACKAGENAME": os.getenv("PYTHON_NUSPEC_PACKAGENAME"),
"PACKAGETITLE": os.getenv("PYTHON_NUSPEC_PACKAGETITLE"),
"FILELIST": r' <file src="**\*" target="tools" />',
}
if not NUSPEC_DATA["PYTHON_VERSION"]:
if VER_NAME:
NUSPEC_DATA["PYTHON_VERSION"] = "{}.{}-{}{}".format(
VER_DOT, VER_MICRO, VER_NAME, VER_SERIAL
)
else:
NUSPEC_DATA["PYTHON_VERSION"] = "{}.{}".format(VER_DOT, VER_MICRO)
if not NUSPEC_DATA["PACKAGETITLE"]:
NUSPEC_DATA["PACKAGETITLE"] = "Python" if IS_X64 else "Python (32-bit)"
if not NUSPEC_DATA["PACKAGENAME"]:
NUSPEC_DATA["PACKAGENAME"] = "python" if IS_X64 else "pythonx86"
FILELIST_WITH_PROPS = r""" <file src="**\*" exclude="python.props" target="tools" />
<file src="python.props" target="build\native" />"""
NUSPEC_TEMPLATE = r"""<?xml version="1.0"?>
<package>
<metadata>
<id>{PACKAGENAME}</id>
<title>{PACKAGETITLE}</title>
<version>{PYTHON_VERSION}</version>
<authors>Python Software Foundation</authors>
<license type="file">tools\LICENSE.txt</license>
<projectUrl>https://www.python.org/</projectUrl>
<description>Installs {PYTHON_BITNESS} Python for use in build scenarios.</description>
<iconUrl>https://www.python.org/static/favicon.ico</iconUrl>
<tags>python</tags>
</metadata>
<files>
{FILELIST}
</files>
</package>
"""
def get_nuspec_layout(ns):
if ns.include_all or ns.include_nuspec:
data = NUSPEC_DATA
if ns.include_all or ns.include_props:
data = dict(data)
data["FILELIST"] = FILELIST_WITH_PROPS
nuspec = NUSPEC_TEMPLATE.format_map(data)
yield "python.nuspec", ("python.nuspec", nuspec.encode("utf-8"))

View file

@ -30,6 +30,7 @@ OPTIONS = {
"launchers": {"help": "specific launchers"},
"appxmanifest": {"help": "an appxmanifest"},
"props": {"help": "a python.props file"},
"nuspec": {"help": "a python.nuspec file"},
"chm": {"help": "the CHM documentation"},
"html-doc": {"help": "the HTML documentation"},
}
@ -60,13 +61,11 @@ PRESETS = {
"stable",
"distutils",
"venv",
"props"
"props",
"nuspec",
],
},
"iot": {
"help": "Windows IoT Core",
"options": ["stable", "pip"],
},
"iot": {"help": "Windows IoT Core", "options": ["stable", "pip"]},
"default": {
"help": "development kit package",
"options": [

View file

@ -11,15 +11,11 @@ import shutil
import subprocess
import sys
__all__ = []
from .filesets import *
__all__ = ["extract_pip_files", "get_pip_layout"]
def public(f):
__all__.append(f.__name__)
return f
@public
def get_pip_dir(ns):
if ns.copy:
if ns.zip_lib:
@ -29,10 +25,23 @@ def get_pip_dir(ns):
return ns.temp / "packages"
@public
def get_pip_layout(ns):
pip_dir = get_pip_dir(ns)
if not pip_dir.is_dir():
log_warning("Failed to find {} - pip will not be included", pip_dir)
else:
pkg_root = "packages/{}" if ns.zip_lib else "Lib/site-packages/{}"
for dest, src in rglob(pip_dir, "**/*"):
yield pkg_root.format(dest), src
yield "pip.ini", ("pip.ini", b"[global]\nuser=yes")
def extract_pip_files(ns):
dest = get_pip_dir(ns)
dest.mkdir(parents=True, exist_ok=True)
try:
dest.mkdir(parents=True, exist_ok=False)
except IOError:
return
src = ns.source / "Lib" / "ensurepip" / "_bundled"
@ -58,6 +67,7 @@ def extract_pip_files(ns):
"--target",
str(dest),
"--no-index",
"--no-compile",
"--no-cache-dir",
"-f",
str(src),

View file

@ -6,13 +6,7 @@ import os
from .constants import *
__all__ = ["PYTHON_PROPS_NAME"]
def public(f):
__all__.append(f.__name__)
return f
__all__ = ["get_props_layout"]
PYTHON_PROPS_NAME = "python.props"
@ -97,14 +91,8 @@ PROPS_TEMPLATE = r"""<?xml version="1.0" encoding="utf-8"?>
"""
@public
def get_props_layout(ns):
if ns.include_all or ns.include_props:
yield "python.props", ns.temp / "python.props"
@public
def get_props(ns):
# TODO: Filter contents of props file according to included/excluded items
props = PROPS_TEMPLATE.format_map(PROPS_DATA)
return props.encode("utf-8")
# TODO: Filter contents of props file according to included/excluded items
props = PROPS_TEMPLATE.format_map(PROPS_DATA)
yield "python.props", ("python.props", props.encode("utf-8"))