Skip to content

Commit ffcd936

Browse files
authored
Update first launch test command (#109)
Fixes #105
1 parent 926f13b commit ffcd936

File tree

6 files changed

+81
-28
lines changed

6 files changed

+81
-28
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ jobs:
165165
download_dir="$i\_cache";
166166
global_dir="$i\_bin";
167167
} | Out-File $env:PYTHON_MANAGER_CONFIG -Encoding utf8
168-
pymanager exec
168+
pymanager install --configure -y
169169
if ($?) { pymanager list }
170170
env:
171171
PYTHON_MANAGER_INCLUDE_UNMANAGED: false

ci/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ stages:
279279
download_dir="$i\_cache";
280280
global_dir="$i\_bin";
281281
} | Out-File $env:PYTHON_MANAGER_CONFIG -Encoding utf8
282-
pymanager exec
282+
pymanager install --configure -y
283283
if ($?) { pymanager list }
284284
displayName: 'Emulate first launch'
285285
env:

src/manage/commands.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,7 @@ def execute(self):
814814
self.show_welcome()
815815
if self.configure:
816816
cmd = FirstRun(["**first_run", "--explicit"], self.root)
817+
cmd.confirm = self.confirm
817818
cmd.execute()
818819
else:
819820
from .install_command import execute

src/manage/firstrun.py

Lines changed: 55 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import os
22
import sys
33
import time
4+
import winreg
45

56
from . import logging
67
from .pathutils import Path
@@ -51,14 +52,20 @@ def check_app_alias(cmd):
5152
LOGGER.debug("Check passed: aliases are correct")
5253
return True
5354

55+
_LONG_PATH_KEY = r"System\CurrentControlSet\Control\FileSystem"
56+
_LONG_PATH_VALUENAME = "LongPathsEnabled"
5457

55-
def check_long_paths(cmd):
58+
def check_long_paths(
59+
cmd,
60+
*,
61+
hive=winreg.HKEY_LOCAL_MACHINE,
62+
keyname=_LONG_PATH_KEY,
63+
valuename=_LONG_PATH_VALUENAME,
64+
):
5665
LOGGER.debug("Checking long paths setting")
57-
import winreg
5866
try:
59-
with winreg.OpenKeyEx(winreg.HKEY_LOCAL_MACHINE,
60-
r"System\CurrentControlSet\Control\FileSystem") as key:
61-
if winreg.QueryValueEx(key, "LongPathsEnabled") == (1, winreg.REG_DWORD):
67+
with winreg.OpenKeyEx(hive, keyname) as key:
68+
if winreg.QueryValueEx(key, valuename) == (1, winreg.REG_DWORD):
6269
LOGGER.debug("Check passed: registry key is OK")
6370
return True
6471
except FileNotFoundError:
@@ -67,6 +74,42 @@ def check_long_paths(cmd):
6774
return False
6875

6976

77+
def do_configure_long_paths(
78+
cmd,
79+
*,
80+
hive=winreg.HKEY_LOCAL_MACHINE,
81+
keyname=_LONG_PATH_KEY,
82+
valuename=_LONG_PATH_VALUENAME,
83+
startfile=os.startfile,
84+
):
85+
LOGGER.debug("Updating long paths setting")
86+
try:
87+
with winreg.CreateKeyEx(hive, keyname) as key:
88+
winreg.SetValueEx(key, valuename, None, winreg.REG_DWORD, 1)
89+
LOGGER.info("The setting has been successfully updated, and will "
90+
"take effect after the next reboot.")
91+
return
92+
except OSError:
93+
pass
94+
if not cmd.confirm:
95+
# Without confirmation, we assume we can't elevate, so attempt
96+
# as the current user and if it fails just print a message.
97+
LOGGER.warn("The setting has not been updated. Please rerun '!B!py "
98+
"install --configure!W! with administrative privileges.")
99+
return
100+
startfile(sys.executable, "runas", "**configure-long-paths", show_cmd=0)
101+
for _ in range(5):
102+
time.sleep(0.25)
103+
if check_long_paths(cmd):
104+
LOGGER.info("The setting has been successfully updated, and will "
105+
"take effect after the next reboot.")
106+
break
107+
else:
108+
LOGGER.warn("The setting may not have been updated. Please "
109+
"visit the additional help link at the end for "
110+
"more assistance.")
111+
112+
70113
def check_py_on_path(cmd):
71114
LOGGER.debug("Checking for legacy py.exe on PATH")
72115
from _native import read_alias_package
@@ -120,7 +163,6 @@ def check_global_dir(cmd):
120163

121164

122165
def _check_global_dir_registry(cmd):
123-
import winreg
124166
with winreg.OpenKeyEx(winreg.HKEY_CURRENT_USER, "Environment") as key:
125167
path, kind = winreg.QueryValueEx(key, "Path")
126168
LOGGER.debug("Current registry path: %s", path)
@@ -139,7 +181,6 @@ def _check_global_dir_registry(cmd):
139181

140182

141183
def do_global_dir_on_path(cmd):
142-
import winreg
143184
added = notified = False
144185
try:
145186
LOGGER.debug("Adding %s to PATH", cmd.global_dir)
@@ -290,17 +331,8 @@ def first_run(cmd):
290331
"may need an administrator to approve, and will require a "
291332
"reboot. Some packages may fail to install without long "
292333
"path support enabled.\n", wrap=True)
293-
if cmd.confirm and not cmd.ask_ny("Update setting now?"):
294-
os.startfile(sys.executable, "runas", "**configure-long-paths", show_cmd=0)
295-
for _ in range(5):
296-
time.sleep(0.25)
297-
if check_long_paths(cmd):
298-
LOGGER.info("The setting has been successfully updated.")
299-
break
300-
else:
301-
LOGGER.warn("The setting may not have been updated. Please "
302-
"visit the additional help link at the end for "
303-
"more assistance.")
334+
if not cmd.confirm or not cmd.ask_ny("Update setting now?"):
335+
do_configure_long_paths(cmd)
304336
elif cmd.explicit:
305337
LOGGER.info("Checked system long paths setting")
306338

@@ -314,10 +346,7 @@ def first_run(cmd):
314346
LOGGER.print("\nThis may interfere with launching the new 'py' "
315347
"command, and may be resolved by uninstalling "
316348
"'!B!Python launcher!W!'.\n", wrap=True)
317-
if (
318-
cmd.confirm and
319-
not cmd.ask_ny("Open Installed apps now?")
320-
):
349+
if cmd.confirm and not cmd.ask_ny("Open Installed apps now?"):
321350
os.startfile("ms-settings:appsfeatures")
322351
elif cmd.explicit:
323352
if r == "skip":
@@ -342,7 +371,7 @@ def first_run(cmd):
342371
"must manually edit environment variables to later "
343372
"remove the entry.\n", wrap=True)
344373
if (
345-
cmd.confirm and
374+
not cmd.confirm or
346375
not cmd.ask_ny("Add commands directory to your PATH now?")
347376
):
348377
do_global_dir_on_path(cmd)
@@ -352,7 +381,7 @@ def first_run(cmd):
352381
else:
353382
LOGGER.info("Checked PATH for versioned commands directory")
354383

355-
# This check must be last, because 'do_install' will exit the program.
384+
# This check must be last, because a failed install may exit the program.
356385
if cmd.check_any_install:
357386
if not check_any_install(cmd):
358387
welcome()
@@ -361,11 +390,11 @@ def first_run(cmd):
361390
LOGGER.print("!Y!You do not have any Python runtimes installed.!W!",
362391
level=logging.WARN)
363392
LOGGER.print("\nInstall the current latest version of CPython? If "
364-
"not, you can use !B!py install default!W! later to "
393+
"not, you can use '!B!py install default!W!' later to "
365394
"install, or one will be installed automatically when "
366395
"needed.\n", wrap=True)
367396
LOGGER.info("")
368-
if cmd.ask_yn("Install CPython now?"):
397+
if not cmd.confirm or cmd.ask_yn("Install CPython now?"):
369398
do_install(cmd)
370399
elif cmd.explicit:
371400
LOGGER.info("Checked for any Python installs")

tests/conftest.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ def localserver():
148148
class FakeConfig:
149149
def __init__(self, global_dir, installs=[]):
150150
self.global_dir = global_dir
151+
self.confirm = False
151152
self.installs = list(installs)
152153
self.shebang_can_run_anything = True
153154
self.shebang_can_run_anything_silently = False

tests/test_firstrun.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,3 +237,25 @@ def test_do_global_dir_path_fail_broadcast(protect_reg, fake_config, assert_log,
237237
monkeypatch.setattr(winreg, "SetValueEx", lambda *a: None)
238238
firstrun.do_global_dir_on_path(fake_config)
239239
assert_log(assert_log.skip_until("Failed to notify of PATH environment.+"))
240+
241+
242+
def test_check_long_paths(registry, fake_config):
243+
assert not firstrun.check_long_paths(fake_config, hive=registry.hive, keyname=registry.root)
244+
registry.setup(LongPathsEnabled=1)
245+
assert firstrun.check_long_paths(fake_config, hive=registry.hive, keyname=registry.root)
246+
247+
248+
def test_do_configure_long_paths(registry, fake_config, monkeypatch):
249+
firstrun.do_configure_long_paths(fake_config, hive=registry.hive, keyname=registry.root, startfile=_raise_oserror)
250+
assert winreg.QueryValueEx(registry.key, "LongPathsEnabled") == (1, winreg.REG_DWORD)
251+
252+
253+
def test_do_configure_long_paths_elevated(protect_reg, fake_config, monkeypatch):
254+
startfile_calls = []
255+
def startfile(*a, **kw):
256+
startfile_calls.append((a, kw))
257+
# Pretend we can interact, so that os.startfile gets called
258+
fake_config.confirm = True
259+
firstrun.do_configure_long_paths(fake_config, startfile=startfile)
260+
assert startfile_calls
261+
assert startfile_calls[0][0][1:] == ("runas", "**configure-long-paths")

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy