diff options
| -rwxr-xr-x | bin/qmk | 44 | ||||
| -rw-r--r-- | lib/python/qmk/cli/__init__.py | 145 | 
2 files changed, 121 insertions, 68 deletions
| @@ -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 | 
