mirror of
				https://github.com/mfulz/qmk_firmware.git
				synced 2025-10-31 05:12:33 +01:00 
			
		
		
		
	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>
This commit is contained in:
		
							parent
							
								
									a3e7f3e7c5
								
							
						
					
					
						commit
						bc38c38f8c
					
				
							
								
								
									
										44
									
								
								bin/qmk
									
									
									
									
									
								
							
							
						
						
									
										44
									
								
								bin/qmk
									
									
									
									
									
								
							| @ -3,7 +3,6 @@ | |||||||
| """ | """ | ||||||
| import os | import os | ||||||
| import sys | import sys | ||||||
| from importlib.util import find_spec |  | ||||||
| from pathlib import Path | from pathlib import Path | ||||||
| 
 | 
 | ||||||
| # Add the QMK python libs to our 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() | python_lib_dir = Path(qmk_dir / 'lib' / 'python').resolve() | ||||||
| sys.path.append(str(python_lib_dir)) | 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 | # Setup the CLI | ||||||
| import milc  # noqa | 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}' | milc.EMOJI_LOGLEVELS['INFO'] = '{fg_blue}Ψ{style_reset_all}' | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -2,33 +2,79 @@ | |||||||
| 
 | 
 | ||||||
| We list each subcommand here explicitly because all the reliable ways of searching for modules are slow and delay startup. | 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 | import sys | ||||||
|  | from importlib.util import find_spec | ||||||
|  | from pathlib import Path | ||||||
|  | from subprocess import run | ||||||
| 
 | 
 | ||||||
| from milc import cli, __VERSION__ | 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 | # Supported version information | ||||||
| # | # | ||||||
| # Based on the OSes we support these are the minimum python version available by default. | # 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('.') | milc_version = __VERSION__.split('.') | ||||||
| 
 | 
 | ||||||
| if int(milc_version[0]) < 2 and int(milc_version[1]) < 3: | if int(milc_version[0]) < 2 and int(milc_version[1]) < 3: | ||||||
|     from pathlib import Path |  | ||||||
| 
 |  | ||||||
|     requirements = Path('requirements.txt').resolve() |     requirements = Path('requirements.txt').resolve() | ||||||
| 
 | 
 | ||||||
|     print(f'Your MILC library is too old! Please upgrade: python3 -m pip install -U -r {str(requirements)}') |     print(f'Your MILC library is too old! Please upgrade: python3 -m pip install -U -r {str(requirements)}') | ||||||
|     exit(127) |     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 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Zach White
						Zach White