qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

commands.py (3827B)


      1 """Helper functions for commands.
      2 """
      3 import os
      4 import sys
      5 import shutil
      6 from pathlib import Path
      7 
      8 from milc import cli
      9 import jsonschema
     10 
     11 from qmk.constants import QMK_USERSPACE, HAS_QMK_USERSPACE
     12 from qmk.json_schema import json_load, validate
     13 from qmk.keyboard import keyboard_alias_definitions
     14 from qmk.util import maybe_exit
     15 from qmk.path import unix_style_path
     16 
     17 
     18 def find_make():
     19     """Returns the correct make command for this environment.
     20     """
     21     make_cmd = os.environ.get('MAKE')
     22 
     23     if not make_cmd:
     24         make_cmd = 'gmake' if shutil.which('gmake') else 'make'
     25 
     26     return make_cmd
     27 
     28 
     29 def get_make_parallel_args(parallel=1):
     30     """Returns the arguments for running the specified number of parallel jobs.
     31     """
     32     parallel_args = []
     33 
     34     if int(parallel) <= 0:
     35         # 0 or -1 means -j without argument (unlimited jobs)
     36         parallel_args.append('--jobs')
     37     elif int(parallel) > 1:
     38         parallel_args.append('--jobs=' + str(parallel))
     39 
     40     if int(parallel) != 1:
     41         # If more than 1 job is used, synchronize parallel output by target
     42         parallel_args.append('--output-sync=target')
     43 
     44     return parallel_args
     45 
     46 
     47 def parse_configurator_json(configurator_file):
     48     """Open and parse a configurator json export
     49     """
     50     user_keymap = json_load(configurator_file)
     51     # Validate against the jsonschema
     52     try:
     53         validate(user_keymap, 'qmk.keymap.v1')
     54 
     55     except jsonschema.ValidationError as e:
     56         cli.log.error(f'Invalid JSON keymap: {configurator_file} : {e.message}')
     57         maybe_exit(1)
     58 
     59     keyboard = user_keymap.get('keyboard', None)
     60     aliases = keyboard_alias_definitions()
     61 
     62     while keyboard in aliases:
     63         last_keyboard = keyboard
     64         keyboard = aliases[keyboard].get('target', keyboard)
     65         if keyboard == last_keyboard:
     66             break
     67 
     68     user_keymap['keyboard'] = keyboard
     69     return user_keymap
     70 
     71 
     72 def parse_env_vars(args):
     73     """Common processing for cli.args.env
     74     """
     75     envs = {}
     76     for env in args:
     77         if '=' in env:
     78             key, value = env.split('=', 1)
     79             envs[key] = value
     80         else:
     81             cli.log.warning('Invalid environment variable: %s', env)
     82     return envs
     83 
     84 
     85 def build_environment(args):
     86     envs = parse_env_vars(args)
     87 
     88     if HAS_QMK_USERSPACE:
     89         envs['QMK_USERSPACE'] = unix_style_path(Path(QMK_USERSPACE).resolve())
     90 
     91     return envs
     92 
     93 
     94 def in_virtualenv():
     95     """Check if running inside a virtualenv.
     96     Based on https://stackoverflow.com/a/1883251
     97     """
     98     active_prefix = getattr(sys, "base_prefix", None) or getattr(sys, "real_prefix", None) or sys.prefix
     99     return active_prefix != sys.prefix
    100 
    101 
    102 def dump_lines(output_file, lines, quiet=True, remove_repeated_newlines=False):
    103     """Handle dumping to stdout or file
    104     Creates parent folders if required
    105     """
    106     generated = '\n'.join(lines) + '\n'
    107     if remove_repeated_newlines:
    108         while '\n\n\n' in generated:
    109             generated = generated.replace('\n\n\n', '\n\n')
    110     if output_file and output_file.name != '-':
    111         output_file.parent.mkdir(parents=True, exist_ok=True)
    112         if output_file.exists():
    113             with open(output_file, 'r', encoding='utf-8', newline='\n') as f:
    114                 existing = f.read()
    115             if existing == generated:
    116                 if not quiet:
    117                     cli.log.info(f'No changes to {output_file.name}.')
    118                 return
    119             output_file.replace(output_file.parent / (output_file.name + '.bak'))
    120         with open(output_file, 'w', encoding='utf-8', newline='\n') as f:
    121             f.write(generated)
    122         # output_file.write_text(generated, encoding='utf-8', newline='\n') # `newline` needs Python 3.10
    123 
    124         if not quiet:
    125             cli.log.info(f'Wrote {output_file.name} to {output_file}.')
    126     else:
    127         print(generated)