summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZach White <skullydazed@gmail.com>2021-05-10 12:00:52 -0700
committerGitHub <noreply@github.com>2021-05-10 12:00:52 -0700
commitbc38c38f8c25dcbe759bc4d9d707a0069b3c6c59 (patch)
tree57cf7b2c3a9953a52ac333819d934687290d4f4b
parenta3e7f3e7c58ee98596ead5c213f3a9ed8340cd80 (diff)
downloadqmk_firmware-bc38c38f8c25dcbe759bc4d9d707a0069b3c6c59.tar.gz
qmk_firmware-bc38c38f8c25dcbe759bc4d9d707a0069b3c6c59.zip
Move the module checking and updating to lib/python (#12416)
* move the module checking and updating to lib/python * make flake8 happy * Update lib/python/qmk/cli/__init__.py Co-authored-by: Erovia <Erovia@users.noreply.github.com> * prompt the user to disable developer mode * pyformat * flake8 Co-authored-by: Erovia <Erovia@users.noreply.github.com>
-rwxr-xr-xbin/qmk44
-rw-r--r--lib/python/qmk/cli/__init__.py145
2 files changed, 121 insertions, 68 deletions
diff --git a/bin/qmk b/bin/qmk
index a3c1be328a..47b50f83b3 100755
--- a/bin/qmk
+++ b/bin/qmk
@@ -3,7 +3,6 @@
"""
import os
import sys
-from importlib.util import find_spec
from pathlib import Path
# Add the QMK python libs to our path
@@ -12,52 +11,9 @@ qmk_dir = script_dir.parent
python_lib_dir = Path(qmk_dir / 'lib' / 'python').resolve()
sys.path.append(str(python_lib_dir))
-
-def _check_modules(requirements):
- """ Check if the modules in the given requirements.txt are available.
- """
- with Path(qmk_dir / requirements).open() as fd:
- for line in fd.readlines():
- line = line.strip().replace('<', '=').replace('>', '=')
-
- if len(line) == 0 or line[0] == '#' or line.startswith('-r'):
- continue
-
- if '#' in line:
- line = line.split('#')[0]
-
- module = dict()
- module['name'] = line.split('=')[0] if '=' in line else line
- module['import'] = module['name'].replace('-', '_')
-
- # Not every module is importable by its own name.
- if module['name'] == "pep8-naming":
- module['import'] = "pep8ext_naming"
-
- if not find_spec(module['import']):
- print('Could not find module %s!' % module['name'])
- print('Please run `python3 -m pip install -r %s` to install required python dependencies.' % (qmk_dir / requirements,))
- if developer:
- print('You can also turn off developer mode: qmk config user.developer=None')
- print()
- exit(255)
-
-
-developer = False
-# Make sure our modules have been setup
-_check_modules('requirements.txt')
-
# Setup the CLI
import milc # noqa
-# For developers additional modules are needed
-if milc.cli.config.user.developer:
- # Do not run the check for 'config',
- # so users can turn off developer mode
- if len(sys.argv) == 1 or (len(sys.argv) > 1 and 'config' != sys.argv[1]):
- developer = True
- _check_modules('requirements-dev.txt')
-
milc.EMOJI_LOGLEVELS['INFO'] = '{fg_blue}Ψ{style_reset_all}'
diff --git a/lib/python/qmk/cli/__init__.py b/lib/python/qmk/cli/__init__.py
index 008e57f762..6fe769fe7b 100644
--- a/lib/python/qmk/cli/__init__.py
+++ b/lib/python/qmk/cli/__init__.py
@@ -2,33 +2,79 @@
We list each subcommand here explicitly because all the reliable ways of searching for modules are slow and delay startup.
"""
+import os
+import shlex
import sys
+from importlib.util import find_spec
+from pathlib import Path
+from subprocess import run
from milc import cli, __VERSION__
+from milc.questions import yesno
-from . import c2json
-from . import cformat
-from . import chibios
-from . import clean
-from . import compile
-from . import config
-from . import docs
-from . import doctor
-from . import fileformat
-from . import flash
-from . import format
-from . import generate
-from . import hello
-from . import info
-from . import json2c
-from . import lint
-from . import list
-from . import kle2json
-from . import multibuild
-from . import new
-from . import pyformat
-from . import pytest
+def _run_cmd(*command):
+ """Run a command in a subshell.
+ """
+ if 'windows' in cli.platform.lower():
+ safecmd = map(shlex.quote, command)
+ safecmd = ' '.join(safecmd)
+ command = [os.environ['SHELL'], '-c', safecmd]
+
+ return run(command)
+
+
+def _find_broken_requirements(requirements):
+ """ Check if the modules in the given requirements.txt are available.
+
+ Args:
+
+ requirements
+ The path to a requirements.txt file
+
+ Returns a list of modules that couldn't be imported
+ """
+ with Path(requirements).open() as fd:
+ broken_modules = []
+
+ for line in fd.readlines():
+ line = line.strip().replace('<', '=').replace('>', '=')
+
+ if len(line) == 0 or line[0] == '#' or line.startswith('-r'):
+ continue
+
+ if '#' in line:
+ line = line.split('#')[0]
+
+ module_name = line.split('=')[0] if '=' in line else line
+ module_import = module_name.replace('-', '_')
+
+ # Not every module is importable by its own name.
+ if module_name == "pep8-naming":
+ module_import = "pep8ext_naming"
+
+ if not find_spec(module_import):
+ broken_modules.append(module_name)
+
+ return broken_modules
+
+
+def _broken_module_imports(requirements):
+ """Make sure we can import all the python modules.
+ """
+ broken_modules = _find_broken_requirements(requirements)
+
+ for module in broken_modules:
+ print('Could not find module %s!' % module)
+
+ if broken_modules:
+ return True
+
+ return False
+
+
+# Make sure our python is new enough
+#
# Supported version information
#
# Based on the OSes we support these are the minimum python version available by default.
@@ -54,9 +100,60 @@ if sys.version_info[0] != 3 or sys.version_info[1] < 7:
milc_version = __VERSION__.split('.')
if int(milc_version[0]) < 2 and int(milc_version[1]) < 3:
- from pathlib import Path
-
requirements = Path('requirements.txt').resolve()
print(f'Your MILC library is too old! Please upgrade: python3 -m pip install -U -r {str(requirements)}')
exit(127)
+
+# Check to make sure we have all our dependencies
+msg_install = 'Please run `python3 -m pip install -r %s` to install required python dependencies.'
+
+if _broken_module_imports('requirements.txt'):
+ if yesno('Would you like to install the required Python modules?'):
+ _run_cmd(sys.executable, '-m', 'pip', 'install', '-r', 'requirements.txt')
+ else:
+ print()
+ print(msg_install % (str(Path('requirements.txt').resolve()),))
+ print()
+ exit(1)
+
+if cli.config.user.developer:
+ args = sys.argv[1:]
+ while args and args[0][0] == '-':
+ del args[0]
+ if not args or args[0] != 'config':
+ if _broken_module_imports('requirements-dev.txt'):
+ if yesno('Would you like to install the required developer Python modules?'):
+ _run_cmd(sys.executable, '-m', 'pip', 'install', '-r', 'requirements-dev.txt')
+ elif yesno('Would you like to disable developer mode?'):
+ _run_cmd(sys.argv[0], 'config', 'user.developer=None')
+ else:
+ print()
+ print(msg_install % (str(Path('requirements-dev.txt').resolve()),))
+ print('You can also turn off developer mode: qmk config user.developer=None')
+ print()
+ exit(1)
+
+# Import our subcommands
+from . import c2json # noqa
+from . import cformat # noqa
+from . import chibios # noqa
+from . import clean # noqa
+from . import compile # noqa
+from . import config # noqa
+from . import docs # noqa
+from . import doctor # noqa
+from . import fileformat # noqa
+from . import flash # noqa
+from . import format # noqa
+from . import generate # noqa
+from . import hello # noqa
+from . import info # noqa
+from . import json2c # noqa
+from . import lint # noqa
+from . import list # noqa
+from . import kle2json # noqa
+from . import multibuild # noqa
+from . import new # noqa
+from . import pyformat # noqa
+from . import pytest # noqa