pw_env_setup: Initial pass at prettier Windows UI
This change improves the Windows env_setup UI to mirror that of POSIX.
Not everything matches yet, and there is still no distinction between
bootstrap and activate.
Change-Id: I8680400340c7af03dbce234a248a65839287e6eb
diff --git a/pw_env_setup/env_setup.bat b/pw_env_setup/env_setup.bat
index 6da9997..7a81b72 100644
--- a/pw_env_setup/env_setup.bat
+++ b/pw_env_setup/env_setup.bat
@@ -30,10 +30,35 @@
set PW_CHECKOUT_ROOT=
)
+:: Allow forcing a specifc Python version through the environment variable
+:: PW_BOOTSTRAP_PYTHON. Otherwise, use the system Python if one exists.
+if not "%PW_BOOTSTRAP_PYTHON%" == "" (
+ set python="%PW_BOOTSTRAP_PYTHON%"
+) else (
+ where python >NUL 2>&1
+ if %ERRORLEVEL% EQU 0 (
+ set python=python
+ ) else (
+ echo.
+ echo Error: no system Python present
+ echo.
+ echo Pigweed's bootstrap process requires a local system Python.
+ echo Please install Python on your system, add it to your PATH
+ echo and re-try running bootstrap.
+ goto finish
+ )
+)
+
+call %python% %PW_ROOT%\pw_env_setup\py\pw_env_setup\windows_env_start.py
+
set shell_file="%PW_ROOT%\pw_env_setup\.env_setup.bat"
if not exist %shell_file% (
- call python %PW_ROOT%\pw_env_setup\py\pw_env_setup\env_setup.py --pw-root %PW_ROOT% --shell-file %shell_file%
+ call %python% %PW_ROOT%\pw_env_setup\py\pw_env_setup\env_setup.py^
+ --pw-root %PW_ROOT%^
+ --shell-file %shell_file%
)
call %shell_file%
+
+:finish
diff --git a/pw_env_setup/py/pw_env_setup/colors.py b/pw_env_setup/py/pw_env_setup/colors.py
new file mode 100644
index 0000000..63cb834
--- /dev/null
+++ b/pw_env_setup/py/pw_env_setup/colors.py
@@ -0,0 +1,39 @@
+# Copyright 2020 The Pigweed Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+"""Defines ANSI color codes."""
+
+import ctypes
+import os
+
+
+def _make_color(*codes):
+ # Apply all the requested ANSI color codes. Note that this is unbalanced
+ # with respect to the reset, which only requires a '0' to erase all codes.
+ start = ''.join('\033[{}m'.format(code) for code in codes)
+ reset = '\033[0m'
+
+ return staticmethod(lambda msg: u'{}{}{}'.format(start, msg, reset))
+
+
+class Color: # pylint: disable=too-few-public-methods
+ """Helpers to surround text with ASCII color escapes"""
+ bold = _make_color(1)
+ green = _make_color(32)
+ magenta = _make_color(35, 1)
+
+
+def enable_colors():
+ if os.name == 'nt':
+ kernel32 = ctypes.windll.kernel32
+ kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
diff --git a/pw_env_setup/py/pw_env_setup/env_setup.py b/pw_env_setup/py/pw_env_setup/env_setup.py
index 7afdaa4..b425b08 100755
--- a/pw_env_setup/py/pw_env_setup/env_setup.py
+++ b/pw_env_setup/py/pw_env_setup/env_setup.py
@@ -69,25 +69,12 @@
# pylint: disable=wrong-import-position
from pw_env_setup.cipd_setup import update as cipd_update
from pw_env_setup.cipd_setup import wrapper as cipd_wrapper
+from pw_env_setup.colors import Color, enable_colors
from pw_env_setup import cargo_setup
from pw_env_setup import environment
from pw_env_setup import virtualenv_setup
-def _make_color(*codes):
- # Apply all the requested ANSI color codes. Note that this is unbalanced
- # with respect to the reset, which only requires a '0' to erase all codes.
- start = ''.join('\033[{}m'.format(code) for code in codes)
- reset = '\033[0m'
-
- return staticmethod(lambda msg: '{}{}{}'.format(start, msg, reset))
-
-
-class _Color: # pylint: disable=too-few-public-methods
- """Helpers to surround text with ASCII color escapes"""
- bold = _make_color(1)
-
-
class _Result:
class Status: # pylint: disable=too-few-public-methods
DONE = 'done'
@@ -140,6 +127,8 @@
def setup(self):
"""Runs each of the env_setup steps."""
+ enable_colors()
+
steps = [
('CIPD package manager', self.cipd),
('Python environment', self.virtualenv),
@@ -156,13 +145,13 @@
# steps.append(("Rust's cargo", self.cargo))
self._log(
- _Color.bold('Downloading and installing packages into local '
- 'source directory:\n'))
+ Color.bold('Downloading and installing packages into local '
+ 'source directory:\n'))
max_name_len = max(len(name) for name, _ in steps)
self._env.echo(
- _Color.bold(
+ Color.bold(
'Activating environment (setting environment variables):'))
self._env.echo('')
@@ -271,7 +260,7 @@
if not self._quiet:
fd.write('echo "{}"\n'.format(
- _Color.bold('Sanity checking the environment:')))
+ Color.bold('Sanity checking the environment:')))
fd.write('{}\n'.format(echo_empty))
log_level = 'warn' if 'PW_ENVSETUP_QUIET' in os.environ else 'info'
@@ -280,14 +269,14 @@
if self._is_windows:
fd.write('{}\n'.format(doctor))
- fd.write('if %ERRORLEVEL% == 0 (\n')
+ fd.write('if %ERRORLEVEL% EQU 0 (\n')
else:
fd.write('if {}; then\n'.format(doctor))
if not self._quiet:
fd.write(' {}\n'.format(echo_empty))
fd.write(' echo "{}"\n'.format(
- _Color.bold('Environment looks good; you are ready to go!')))
+ Color.bold('Environment looks good; you are ready to go!')))
if self._is_windows:
fd.write(')\n')
diff --git a/pw_env_setup/py/pw_env_setup/environment.py b/pw_env_setup/py/pw_env_setup/environment.py
index fe14fc9..9154eef 100644
--- a/pw_env_setup/py/pw_env_setup/environment.py
+++ b/pw_env_setup/py/pw_env_setup/environment.py
@@ -54,10 +54,16 @@
self._check()
def _check(self):
- if not isinstance(self.name, str):
+ try:
+ # In python2, unicode is a distinct type.
+ valid_types = (str, unicode) # pylint: disable=undefined-variable
+ except NameError:
+ valid_types = (str, )
+
+ if not isinstance(self.name, valid_types):
raise BadNameType('variable name {!r} not of type str'.format(
self.name))
- if not isinstance(self.value, str):
+ if not isinstance(self.value, valid_types):
raise BadValueType('{!r} value {!r} not of type str'.format(
self.name, self.value))
diff --git a/pw_env_setup/py/pw_env_setup/windows_env_start.py b/pw_env_setup/py/pw_env_setup/windows_env_start.py
new file mode 100644
index 0000000..dc81260
--- /dev/null
+++ b/pw_env_setup/py/pw_env_setup/windows_env_start.py
@@ -0,0 +1,67 @@
+# -*- coding: utf-8 -*-
+
+# Copyright 2020 The Pigweed Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+"""Prints the env_setup banner for cmd.exe.
+
+This is done from Python as activating colors and printing ASCII art are not
+easy to do in cmd.exe. Activated colors also don't persist in the parent
+process.
+"""
+
+from __future__ import print_function
+
+import os
+import sys
+
+from colors import Color, enable_colors
+
+_PIGWEED_BANNER = u'''
+ ▒█████▄ █▓ ▄███▒ ▒█ ▒█ ░▓████▒ ░▓████▒ ▒▓████▄
+ ▒█░ █░ ░█▒ ██▒ ▀█▒ ▒█░ █ ▒█ ▒█ ▀ ▒█ ▀ ▒█ ▀█▌
+ ▒█▄▄▄█░ ░█▒ █▓░ ▄▄░ ▒█░ █ ▒█ ▒███ ▒███ ░█ █▌
+ ▒█▀ ░█░ ▓█ █▓ ░█░ █ ▒█ ▒█ ▄ ▒█ ▄ ░█ ▄█▌
+ ▒█ ░█░ ░▓███▀ ▒█▓▀▓█░ ░▓████▒ ░▓████▒ ▒▓████▀
+'''
+
+
+def main():
+ if os.name != 'nt':
+ return 1
+
+ enable_colors()
+
+ print(Color.green('\n WELCOME TO...'))
+ print(Color.magenta(_PIGWEED_BANNER))
+
+ bootstrap = True
+
+ if bootstrap:
+ print(
+ Color.green('\n BOOTSTRAP! Bootstrap may take a few minutes; '
+ 'please be patient'))
+ print(
+ Color.green(
+ ' On Windows, this stage is extremely slow (~10 minutes).\n'))
+ else:
+ print(
+ Color.green(
+ '\n ACTIVATOR! This sets your console environment variables.')
+ )
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/pw_presubmit/py/pw_presubmit/pigweed_presubmit.py b/pw_presubmit/py/pw_presubmit/pigweed_presubmit.py
index 710643d..8330cde 100755
--- a/pw_presubmit/py/pw_presubmit/pigweed_presubmit.py
+++ b/pw_presubmit/py/pw_presubmit/pigweed_presubmit.py
@@ -313,7 +313,7 @@
# Skip shebang and blank lines
line = file.readline()
while line and (line.startswith(
- ('#!', '/*', '@echo off')) or not line.strip()):
+ ('#!', '/*', '@echo off', '# -*-')) or not line.strip()):
line = file.readline()
first_line = COPYRIGHT_FIRST_LINE.match(line)