Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions .azure-pipelines/windows-appx-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
jobs:
- job: Prebuild
displayName: Pre-build checks

pool:
vmImage: ubuntu-16.04

steps:
- template: ./prebuild-checks.yml


- job: Windows_Appx_Tests
displayName: Windows Appx Tests
dependsOn: Prebuild
condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true'))

pool:
vmImage: vs2017-win2016

strategy:
matrix:
win64:
arch: amd64
buildOpt: '-p x64'
testRunTitle: '$(Build.SourceBranchName)-win64-appx'
testRunPlatform: win64
maxParallel: 2

steps:
- checkout: self
clean: true
fetchDepth: 5

- powershell: |
# Relocate build outputs outside of source directory to make cleaning faster
Write-Host '##vso[task.setvariable variable=Py_IntDir]$(Build.BinariesDirectory)\obj'
# UNDONE: Do not build to a different directory because of broken tests
Write-Host '##vso[task.setvariable variable=Py_OutDir]$(Build.SourcesDirectory)\PCbuild'
Write-Host '##vso[task.setvariable variable=EXTERNAL_DIR]$(Build.BinariesDirectory)\externals'
displayName: Update build locations

- script: PCbuild\build.bat -e $(buildOpt)
displayName: 'Build CPython'

- script: python.bat PC\layout -vv -s "$(Build.SourcesDirectory)" -b "$(Py_OutDir)\$(arch)" -t "$(Py_IntDir)\layout-tmp-$(arch)" --copy "$(Py_IntDir)\layout-$(arch)" --precompile --preset-appx --include-tests
displayName: 'Create APPX layout'

- script: .\python.exe -m test.pythoninfo
workingDirectory: $(Py_IntDir)\layout-$(arch)
displayName: 'Display build info'

- script: .\python.exe -m test -q -uall -u-cpu -rwW --slowest --timeout=1200 -j0 --junit-xml="$(Build.BinariesDirectory)\test-results.xml" --tempdir "$(Py_IntDir)\tmp-$(arch)"
workingDirectory: $(Py_IntDir)\layout-$(arch)
displayName: 'Tests'
env:
PREFIX: $(Py_IntDir)\layout-$(arch)

- task: PublishTestResults@2
displayName: 'Publish Test Results'
inputs:
testResultsFiles: '$(Build.BinariesDirectory)\test-results.xml'
mergeTestResults: true
testRunTitle: $(testRunTitle)
platform: $(testRunPlatform)
condition: succeededOrFailed()
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

# Specific binary files
Lib/test/sndhdrdata/sndhdr.* binary
PC/classicAppCompat.* binary

# Text files that should not be subject to eol conversion
Lib/test/cjkencodings/* -text
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_pathlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -1519,7 +1519,7 @@ def test_resolve_common(self):
# resolves to 'dirB/..' first before resolving to parent of dirB.
self._check_resolve_relative(p, P(BASE, 'foo', 'in', 'spam'), False)
# Now create absolute symlinks
d = support._longpath(tempfile.mkdtemp(suffix='-dirD'))
d = support._longpath(tempfile.mkdtemp(suffix='-dirD', dir=os.getcwd()))
self.addCleanup(support.rmtree, d)
os.symlink(os.path.join(d), join('dirA', 'linkX'))
os.symlink(join('dirB'), os.path.join(d, 'linkY'))
Expand Down
1 change: 1 addition & 0 deletions Lib/test/test_venv.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ def test_isolation(self):
self.assertIn('include-system-site-packages = %s\n' % s, data)

@unittest.skipUnless(can_symlink(), 'Needs symlinks')
@unittest.skipIf(os.name == 'nt', 'Symlinks are never used on Windows')
def test_symlinking(self):
"""
Test symlinking works as expected
Expand Down
69 changes: 32 additions & 37 deletions Lib/venv/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import shutil
import subprocess
import sys
import sysconfig
import types

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -63,10 +64,11 @@ def create(self, env_dir):
self.system_site_packages = False
self.create_configuration(context)
self.setup_python(context)
if not self.upgrade:
self.setup_scripts(context)
if self.with_pip:
self._setup_pip(context)
if not self.upgrade:
self.setup_scripts(context)
self.post_setup(context)
if true_system_site_packages:
# We had set it to False before, now
Expand Down Expand Up @@ -157,14 +159,6 @@ def create_configuration(self, context):
f.write('include-system-site-packages = %s\n' % incl)
f.write('version = %d.%d.%d\n' % sys.version_info[:3])

if os.name == 'nt':
def include_binary(self, f):
if f.endswith(('.pyd', '.dll')):
result = True
else:
result = f.startswith('python') and f.endswith('.exe')
return result

def symlink_or_copy(self, src, dst, relative_symlinks_ok=False):
"""
Try symlinking a file, and if that fails, fall back to copying.
Expand Down Expand Up @@ -194,9 +188,9 @@ def setup_python(self, context):
binpath = context.bin_path
path = context.env_exe
copier = self.symlink_or_copy
copier(context.executable, path)
dirname = context.python_dir
if os.name != 'nt':
copier(context.executable, path)
if not os.path.islink(path):
os.chmod(path, 0o755)
for suffix in ('python', 'python3'):
Expand All @@ -208,32 +202,33 @@ def setup_python(self, context):
if not os.path.islink(path):
os.chmod(path, 0o755)
else:
subdir = 'DLLs'
include = self.include_binary
files = [f for f in os.listdir(dirname) if include(f)]
for f in files:
src = os.path.join(dirname, f)
dst = os.path.join(binpath, f)
if dst != context.env_exe: # already done, above
copier(src, dst)
dirname = os.path.join(dirname, subdir)
if os.path.isdir(dirname):
files = [f for f in os.listdir(dirname) if include(f)]
for f in files:
src = os.path.join(dirname, f)
dst = os.path.join(binpath, f)
copier(src, dst)
# copy init.tcl over
for root, dirs, files in os.walk(context.python_dir):
if 'init.tcl' in files:
tcldir = os.path.basename(root)
tcldir = os.path.join(context.env_dir, 'Lib', tcldir)
if not os.path.exists(tcldir):
os.makedirs(tcldir)
src = os.path.join(root, 'init.tcl')
dst = os.path.join(tcldir, 'init.tcl')
shutil.copyfile(src, dst)
break
# For normal cases, the venvlauncher will be copied from
# our scripts folder. For builds, we need to copy it
# manually.
if sysconfig.is_python_build(True):
suffix = '.exe'
if context.python_exe.lower().endswith('_d.exe'):
suffix = '_d.exe'

src = os.path.join(dirname, "venvlauncher" + suffix)
dst = os.path.join(binpath, context.python_exe)
copier(src, dst)

src = os.path.join(dirname, "venvwlauncher" + suffix)
dst = os.path.join(binpath, "pythonw" + suffix)
copier(src, dst)

# copy init.tcl over
for root, dirs, files in os.walk(context.python_dir):
if 'init.tcl' in files:
tcldir = os.path.basename(root)
tcldir = os.path.join(context.env_dir, 'Lib', tcldir)
if not os.path.exists(tcldir):
os.makedirs(tcldir)
src = os.path.join(root, 'init.tcl')
dst = os.path.join(tcldir, 'init.tcl')
shutil.copyfile(src, dst)
break

def _setup_pip(self, context):
"""Installs or upgrades pip in a virtual environment"""
Expand Down Expand Up @@ -320,7 +315,7 @@ def install_scripts(self, context, path):
dstfile = os.path.join(dstdir, f)
with open(srcfile, 'rb') as f:
data = f.read()
if not srcfile.endswith('.exe'):
if not srcfile.endswith(('.exe', '.pdb')):
try:
data = data.decode('utf-8')
data = self.replace_variables(data, context)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Adds support for building a Windows App Store package
1 change: 1 addition & 0 deletions PC/classicAppCompat.can.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<CustomCapabilityDescriptor xmlns="http://schemas.microsoft.com/appx/2016/sccd" xmlns:s="http://schemas.microsoft.com/appx/2016/sccd"><CustomCapabilities><CustomCapability Name="Microsoft.classicAppCompat_8wekyb3d8bbwe"></CustomCapability></CustomCapabilities><AuthorizedEntities><AuthorizedEntity AppPackageFamilyName="PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0" CertificateSignatureHash="0000000000000000000000000000000000000000000000000000000000000000"></AuthorizedEntity><AuthorizedEntity AppPackageFamilyName="PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0" CertificateSignatureHash="0000000000000000000000000000000000000000000000000000000000000000"></AuthorizedEntity><AuthorizedEntity AppPackageFamilyName="PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0" CertificateSignatureHash="0000000000000000000000000000000000000000000000000000000000000000"></AuthorizedEntity><AuthorizedEntity AppPackageFamilyName="PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0" CertificateSignatureHash="0000000000000000000000000000000000000000000000000000000000000000"></AuthorizedEntity><AuthorizedEntity AppPackageFamilyName="PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0" CertificateSignatureHash="0000000000000000000000000000000000000000000000000000000000000000"></AuthorizedEntity><AuthorizedEntity AppPackageFamilyName="PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0" CertificateSignatureHash="0000000000000000000000000000000000000000000000000000000000000000"></AuthorizedEntity><AuthorizedEntity AppPackageFamilyName="PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0" CertificateSignatureHash="0000000000000000000000000000000000000000000000000000000000000000"></AuthorizedEntity><AuthorizedEntity AppPackageFamilyName="PythonSoftwareFoundation.Python.3.14_qbz5n2kfra8p0" CertificateSignatureHash="0000000000000000000000000000000000000000000000000000000000000000"></AuthorizedEntity><AuthorizedEntity AppPackageFamilyName="PythonSoftwareFoundation.Python.3.15_qbz5n2kfra8p0" CertificateSignatureHash="0000000000000000000000000000000000000000000000000000000000000000"></AuthorizedEntity><AuthorizedEntity AppPackageFamilyName="PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0" CertificateSignatureHash="279cd652c4e252bfbe5217ac722205d7729ba409148cfa9e6d9e5b1cb94eaff1"></AuthorizedEntity><AuthorizedEntity AppPackageFamilyName="PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0" CertificateSignatureHash="279cd652c4e252bfbe5217ac722205d7729ba409148cfa9e6d9e5b1cb94eaff1"></AuthorizedEntity><AuthorizedEntity AppPackageFamilyName="PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0" CertificateSignatureHash="279cd652c4e252bfbe5217ac722205d7729ba409148cfa9e6d9e5b1cb94eaff1"></AuthorizedEntity><AuthorizedEntity AppPackageFamilyName="PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0" CertificateSignatureHash="279cd652c4e252bfbe5217ac722205d7729ba409148cfa9e6d9e5b1cb94eaff1"></AuthorizedEntity><AuthorizedEntity AppPackageFamilyName="PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0" CertificateSignatureHash="279cd652c4e252bfbe5217ac722205d7729ba409148cfa9e6d9e5b1cb94eaff1"></AuthorizedEntity><AuthorizedEntity AppPackageFamilyName="PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0" CertificateSignatureHash="279cd652c4e252bfbe5217ac722205d7729ba409148cfa9e6d9e5b1cb94eaff1"></AuthorizedEntity><AuthorizedEntity AppPackageFamilyName="PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0" CertificateSignatureHash="279cd652c4e252bfbe5217ac722205d7729ba409148cfa9e6d9e5b1cb94eaff1"></AuthorizedEntity><AuthorizedEntity AppPackageFamilyName="PythonSoftwareFoundation.Python.3.14_qbz5n2kfra8p0" CertificateSignatureHash="279cd652c4e252bfbe5217ac722205d7729ba409148cfa9e6d9e5b1cb94eaff1"></AuthorizedEntity><AuthorizedEntity AppPackageFamilyName="PythonSoftwareFoundation.Python.3.15_qbz5n2kfra8p0" CertificateSignatureHash="279cd652c4e252bfbe5217ac722205d7729ba409148cfa9e6d9e5b1cb94eaff1"></AuthorizedEntity></AuthorizedEntities></CustomCapabilityDescriptor>
Binary file added PC/classicAppCompat.cat
Binary file not shown.
28 changes: 28 additions & 0 deletions PC/classicAppCompat.sccd

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion PC/getpathp.c
Original file line number Diff line number Diff line change
Expand Up @@ -536,10 +536,16 @@ static _PyInitError
get_program_full_path(const _PyCoreConfig *core_config,
PyCalculatePath *calculate, _PyPathConfig *config)
{
const wchar_t *pyvenv_launcher;
wchar_t program_full_path[MAXPATHLEN+1];
memset(program_full_path, 0, sizeof(program_full_path));

if (!GetModuleFileNameW(NULL, program_full_path, MAXPATHLEN)) {
/* The launcher may need to force the executable path to a
* different environment, so override it here. */
pyvenv_launcher = _wgetenv(L"__PYVENV_LAUNCHER__");
if (pyvenv_launcher && pyvenv_launcher[0]) {
wcscpy_s(program_full_path, MAXPATHLEN+1, pyvenv_launcher);
} else if (!GetModuleFileNameW(NULL, program_full_path, MAXPATHLEN)) {
/* GetModuleFileName should never fail when passed NULL */
return _Py_INIT_ERR("Cannot determine program path");
}
Expand Down
Binary file added PC/icons/pythonwx150.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added PC/icons/pythonwx44.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added PC/icons/pythonx150.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added PC/icons/pythonx44.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added PC/icons/pythonx50.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading