qmk_firmware

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

community_modules.py (3149B)


      1 import os
      2 
      3 from pathlib import Path
      4 from functools import lru_cache
      5 
      6 from milc.attrdict import AttrDict
      7 
      8 from qmk.json_schema import json_load, validate, merge_ordered_dicts
      9 from qmk.util import truthy
     10 from qmk.constants import QMK_FIRMWARE, QMK_USERSPACE, HAS_QMK_USERSPACE
     11 from qmk.path import under_qmk_firmware, under_qmk_userspace
     12 
     13 COMMUNITY_MODULE_JSON_FILENAME = 'qmk_module.json'
     14 
     15 
     16 class ModuleAPI(AttrDict):
     17     def __init__(self, **kwargs):
     18         super().__init__()
     19         for key, value in kwargs.items():
     20             self[key] = value
     21 
     22 
     23 @lru_cache(maxsize=1)
     24 def module_api_list():
     25     module_definition_files = sorted(set(QMK_FIRMWARE.glob('data/constants/module_hooks/*.hjson')))
     26     module_definition_jsons = [json_load(f) for f in module_definition_files]
     27     module_definitions = merge_ordered_dicts(module_definition_jsons)
     28     latest_module_version = module_definition_files[-1].stem
     29     latest_module_version_parts = latest_module_version.split('.')
     30 
     31     api_list = []
     32     for name, mod in module_definitions.items():
     33         api_list.append(ModuleAPI(
     34             ret_type=mod['ret_type'],
     35             name=name,
     36             args=mod['args'],
     37             call_params=mod.get('call_params', ''),
     38             guard=mod.get('guard', None),
     39             header=mod.get('header', None),
     40         ))
     41 
     42     return api_list, latest_module_version, latest_module_version_parts[0], latest_module_version_parts[1], latest_module_version_parts[2]
     43 
     44 
     45 def find_available_module_paths():
     46     """Find all available modules.
     47     """
     48     search_dirs = []
     49     if HAS_QMK_USERSPACE:
     50         search_dirs.append(QMK_USERSPACE / 'modules')
     51     search_dirs.append(QMK_FIRMWARE / 'modules')
     52 
     53     modules = []
     54     for search_dir in search_dirs:
     55         for module_json_path in search_dir.rglob(COMMUNITY_MODULE_JSON_FILENAME):
     56             modules.append(module_json_path.parent)
     57     return modules
     58 
     59 
     60 def find_module_path(module):
     61     """Find a module by name.
     62     """
     63     for module_path in find_available_module_paths():
     64         # Ensure the module directory is under QMK Firmware or QMK Userspace
     65         relative_path = under_qmk_firmware(module_path)
     66         if not relative_path:
     67             relative_path = under_qmk_userspace(module_path)
     68         if not relative_path:
     69             continue
     70 
     71         lhs = str(relative_path.as_posix())[len('modules/'):]
     72         rhs = str(Path(module).as_posix())
     73 
     74         if relative_path and lhs == rhs:
     75             return module_path
     76     return None
     77 
     78 
     79 def load_module_json(module):
     80     """Load a module JSON file.
     81     """
     82     module_path = find_module_path(module)
     83     if not module_path:
     84         raise FileNotFoundError(f'Module not found: {module}')
     85 
     86     module_json = json_load(module_path / COMMUNITY_MODULE_JSON_FILENAME)
     87 
     88     if not truthy(os.environ.get('SKIP_SCHEMA_VALIDATION'), False):
     89         validate(module_json, 'qmk.community_module.v1')
     90 
     91     module_json['module'] = module
     92     module_json['module_path'] = module_path
     93 
     94     return module_json
     95 
     96 
     97 def load_module_jsons(modules):
     98     """Load the module JSON files, matching the specified order.
     99     """
    100     return list(map(load_module_json, modules))