forked from mirrors/qmk_firmware
Compare commits
8 commits
develop
...
python_opt
Author | SHA1 | Date | |
---|---|---|---|
|
e293bf243d | ||
|
286acfe7fd | ||
|
6d20b28354 | ||
|
846da06380 | ||
|
243fc17e41 | ||
|
f394f23ac6 | ||
|
0ca53fa307 | ||
|
8c361d6c41 |
22 changed files with 661 additions and 507 deletions
|
@ -1,34 +1,22 @@
|
|||
{
|
||||
"$id": "qmk.api.keyboard.v1",
|
||||
"allOf": [
|
||||
{"$ref": "qmk.keyboard.v1"},
|
||||
{
|
||||
"$id": "qmk.api.keyboard.v1",
|
||||
"properties": {
|
||||
"keymaps": {
|
||||
"type": "string"
|
||||
},
|
||||
"parse_errors": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"url": {"type": "string"}
|
||||
}
|
||||
|
||||
},
|
||||
"parse_warnings": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"processor_type": {
|
||||
"type": "string"
|
||||
},
|
||||
"protocol": {
|
||||
"type": "string"
|
||||
},
|
||||
"keyboard_folder": {
|
||||
"type": "string"
|
||||
},
|
||||
"platform": {
|
||||
"type": "string"
|
||||
"parse_errors": {"$ref": "qmk.definitions.v1#/string_array"},
|
||||
"parse_warnings": {"$ref": "qmk.definitions.v1#/string_array"},
|
||||
"processor_type": {"type": "string"},
|
||||
"protocol": {"type": "string"},
|
||||
"keyboard_folder": {"type": "string"},
|
||||
"platform": {"type": "string"}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
107
data/schemas/definitions.jsonschema
Normal file
107
data/schemas/definitions.jsonschema
Normal file
|
@ -0,0 +1,107 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"$id": "qmk.definitions.v1",
|
||||
"title": "Common definitions used across QMK's jsonschemas.",
|
||||
"type": "object",
|
||||
"boolean_array": {
|
||||
"type": "object",
|
||||
"additionalProperties": {"type": "boolean"}
|
||||
},
|
||||
"filename": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"pattern": "^[0-9a-z_]*$"
|
||||
},
|
||||
"hex_number_2d": {
|
||||
"type": "string",
|
||||
"pattern": "^0x[0-9A-F]{2}$"
|
||||
},
|
||||
"hex_number_4d": {
|
||||
"type": "string",
|
||||
"pattern": "^0x[0-9A-F]{4}$"
|
||||
},
|
||||
"text_identifier": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 250
|
||||
},
|
||||
"layout_macro": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"enum": ["LAYOUT", "LAYOUT_planck_1x2uC"]
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^LAYOUT_[0-9a-z_]*$"
|
||||
}
|
||||
]
|
||||
},
|
||||
"key_unit": {
|
||||
"type": "number",
|
||||
"min": 0.25
|
||||
},
|
||||
"mcu_pin_array": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/mcu_pin"}
|
||||
},
|
||||
"mcu_pin": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^[A-K]\\d{1,2}$"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^LINE_PIN\\d{1,2}$"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"multipleOf": 1
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"signed_decimal": {
|
||||
"type": "number"
|
||||
},
|
||||
"signed_int": {
|
||||
"type": "number",
|
||||
"multipleOf": 1
|
||||
}
|
||||
"signed_int_8": {
|
||||
"type": "number",
|
||||
"min": -127,
|
||||
"max": 127,
|
||||
"multipleOf": 1
|
||||
}
|
||||
"string_array": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"string_object": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"unsigned_decimal": {
|
||||
"type": "number",
|
||||
"min": 0
|
||||
},
|
||||
"unsigned_int": {
|
||||
"type": "number",
|
||||
"min": 0,
|
||||
"multipleOf": 1
|
||||
}
|
||||
"unsigned_int_8": {
|
||||
"type": "number",
|
||||
"min": 0,
|
||||
"max": 255,
|
||||
"multipleOf": 1
|
||||
}
|
||||
}
|
|
@ -1,24 +1,12 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/schema#",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"$id": "qmk.keyboard.v1",
|
||||
"title": "Keyboard Information",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"keyboard_name": {
|
||||
"type": "string",
|
||||
"minLength": 2,
|
||||
"maxLength": 250
|
||||
},
|
||||
"maintainer": {
|
||||
"type": "string",
|
||||
"minLength": 2,
|
||||
"maxLength": 250
|
||||
},
|
||||
"manufacturer": {
|
||||
"type": "string",
|
||||
"minLength": 2,
|
||||
"maxLength": 250
|
||||
},
|
||||
"keyboard_name": {"$ref": "qmk.definitions.v1#/text_identifier"},
|
||||
"maintainer": {"$ref": "qmk.definitions.v1#/text_identifier"},
|
||||
"manufacturer": {"$ref": "qmk.definitions.v1#/text_identifier"},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"format": "uri"
|
||||
|
@ -40,62 +28,25 @@
|
|||
"type": "string",
|
||||
"enum": ["COL2ROW", "ROW2COL"]
|
||||
},
|
||||
"debounce": {
|
||||
"type": "number",
|
||||
"min": 0,
|
||||
"multipleOf": 1
|
||||
},
|
||||
"height": {
|
||||
"type": "number",
|
||||
"min": 0.25
|
||||
},
|
||||
"width": {
|
||||
"type": "number",
|
||||
"min": 0.25
|
||||
},
|
||||
"debounce": {"$ref": "qmk.definitions.v1#/unsigned_int"},
|
||||
"height": {"$ref": "qmk.definitions.v1#/key_unit"},
|
||||
"width": {"$ref": "qmk.definitions.v1#/key_unit"},
|
||||
"community_layouts": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"minLength": 2,
|
||||
"pattern": "^[0-9a-z_]*$"
|
||||
}
|
||||
},
|
||||
"features": {
|
||||
"type": "object",
|
||||
"additionalProperties": {"type": "boolean"}
|
||||
"items": {"$ref": "qmk.definitions.v1#/filename"}
|
||||
},
|
||||
"features": {"$ref": "qmk.definitions.v1#/boolean_array"},
|
||||
"indicators": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"caps_lock": {
|
||||
"type": "string",
|
||||
"pattern": "^[A-K]\\d{1,2}$"
|
||||
},
|
||||
"num_lock": {
|
||||
"type": "string",
|
||||
"pattern": "^[A-K]\\d{1,2}$"
|
||||
},
|
||||
"scroll_lock": {
|
||||
"type": "string",
|
||||
"pattern": "^[A-K]\\d{1,2}$"
|
||||
}
|
||||
"caps_lock": {"$ref": "qmk.definitions.v1#/mcu_pin"},
|
||||
"num_lock": {"$ref": "qmk.definitions.v1#/mcu_pin"},
|
||||
"scroll_lock": {"$ref": "qmk.definitions.v1#/mcu_pin"}
|
||||
}
|
||||
},
|
||||
"layout_aliases": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"enum": ["LAYOUT", "LAYOUT_planck_1x2uC"]
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^LAYOUT_[0-9a-z_]*$"
|
||||
}
|
||||
]
|
||||
}
|
||||
"additionalProperties": {"$ref": "qmk.definitions.v1#/layout_macro"}
|
||||
},
|
||||
"layouts": {
|
||||
"type": "object",
|
||||
|
@ -109,11 +60,7 @@
|
|||
"c_macro": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"key_count": {
|
||||
"type": "number",
|
||||
"min": 0,
|
||||
"multipleOf": 1
|
||||
},
|
||||
"key_count": {"$ref": "qmk.definitions.v1#/key_unit"},
|
||||
"layout": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
|
@ -131,34 +78,14 @@
|
|||
"multipleOf": 1
|
||||
}
|
||||
},
|
||||
"h": {
|
||||
"type": "number",
|
||||
"min": 0.25
|
||||
},
|
||||
"r": {
|
||||
"type": "number",
|
||||
"min": 0
|
||||
},
|
||||
"rx": {
|
||||
"type": "number",
|
||||
"min": 0
|
||||
},
|
||||
"ry": {
|
||||
"type": "number",
|
||||
"min": 0
|
||||
},
|
||||
"w": {
|
||||
"type": "number",
|
||||
"min": 0.25
|
||||
},
|
||||
"x": {
|
||||
"type": "number",
|
||||
"min": 0
|
||||
},
|
||||
"y": {
|
||||
"type": "number",
|
||||
"min": 0
|
||||
}
|
||||
"key_count": {"$ref": "qmk.definitions.v1#/key_unit"},
|
||||
"r": {"$ref": "qmk.definitions.v1#/unsigned_decimal"},
|
||||
"rx": {"$ref": "qmk.definitions.v1#/unsigned_decimal"},
|
||||
"ry": {"$ref": "qmk.definitions.v1#/unsigned_decimal"},
|
||||
"h": {"$ref": "qmk.definitions.v1#/key_unit"},
|
||||
"w": {"$ref": "qmk.definitions.v1#/key_unit"},
|
||||
"x": {"$ref": "qmk.definitions.v1#/key_unit"},
|
||||
"y": {"$ref": "qmk.definitions.v1#/key_unit"}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -171,73 +98,10 @@
|
|||
"properties": {
|
||||
"direct": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^[A-K]\\d{1,2}$"
|
||||
"items": {$ref": "qmk.definitions.v1#/mcu_pin_array"}
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^LINE_PIN\\d{1,2}$"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"multipleOf": 1
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"cols": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^[A-K]\\d{1,2}$"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^LINE_PIN\\d{1,2}$"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"multipleOf": 1
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"rows": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^[A-K]\\d{1,2}$"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^LINE_PIN\\d{1,2}$"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"multipleOf": 1
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
"cols": {"$ref": "qmk.definitions.v1#/mcu_pin_array"},
|
||||
"rows": {"$ref": "qmk.definitions.v1#/mcu_pin_array"}
|
||||
}
|
||||
},
|
||||
"rgblight": {
|
||||
|
@ -250,47 +114,19 @@
|
|||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"brightness_steps": {
|
||||
"type": "number",
|
||||
"min": 0,
|
||||
"multipleOf": 1
|
||||
},
|
||||
"hue_steps": {
|
||||
"type": "number",
|
||||
"min": 0,
|
||||
"multipleOf": 1
|
||||
},
|
||||
"led_count": {
|
||||
"type": "number",
|
||||
"min": 0,
|
||||
"multipleOf": 1
|
||||
},
|
||||
"max_brightness": {
|
||||
"type": "number",
|
||||
"min": 0,
|
||||
"max": 255,
|
||||
"multipleOf": 1
|
||||
},
|
||||
"pin": {
|
||||
"type": "string",
|
||||
"pattern": "^([A-K]\\d{1,2}|LINE_PIN\\d{1,2})$"
|
||||
},
|
||||
"saturation_steps": {
|
||||
"type": "number",
|
||||
"min": 0,
|
||||
"multipleOf": 1
|
||||
},
|
||||
"brightness_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"},
|
||||
"hue_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"},
|
||||
"led_count": {"$ref": "qmk.definitions.v1#/unsigned_int"},
|
||||
"max_brightness": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
|
||||
"pin": {"$ref": "qmk.definitions.v1#/mcu_pin"},
|
||||
"saturation_steps": {"$ref": "qmk.definitions.v1#/unsigned_int"},
|
||||
"sleep": {"type": "boolean"},
|
||||
"split": {"type": "boolean"},
|
||||
"split_count": {
|
||||
"type": "array",
|
||||
"minLength": 2,
|
||||
"maxLength": 2,
|
||||
"items": {
|
||||
"type": "number",
|
||||
"min": 0,
|
||||
"multipleOf": 1
|
||||
}
|
||||
"items": {"$ref": "qmk.definitions.v1#/unsigned_int"}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -298,40 +134,19 @@
|
|||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"device_ver": {
|
||||
"type": "string",
|
||||
"pattern": "^[0-9A-F]x[0-9A-F][0-9A-F][0-9A-F][0-9A-F]"
|
||||
},
|
||||
"pid": {
|
||||
"type": "string",
|
||||
"pattern": "^[0-9A-F]x[0-9A-F][0-9A-F][0-9A-F][0-9A-F]"
|
||||
},
|
||||
"vid": {
|
||||
"type": "string",
|
||||
"pattern": "^[0-9A-F]x[0-9A-F][0-9A-F][0-9A-F][0-9A-F]"
|
||||
}
|
||||
"device_ver": {"$ref": "qmk.definitions.v1#/hex_number_4d"},
|
||||
"pid": {"$ref": "qmk.definitions.v1#/hex_number_4d"},
|
||||
"vid": {"$ref": "qmk.definitions.v1#/hex_number_4d"}
|
||||
}
|
||||
},
|
||||
"qmk_lufa_bootloader": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"esc_output": {
|
||||
"type": "string",
|
||||
"pattern": "^[A-K]\\d{1,2}$"
|
||||
},
|
||||
"esc_input": {
|
||||
"type": "string",
|
||||
"pattern": "^[A-K]\\d{1,2}$"
|
||||
},
|
||||
"led": {
|
||||
"type": "string",
|
||||
"pattern": "^[A-K]\\d{1,2}$"
|
||||
},
|
||||
"speaker": {
|
||||
"type": "string",
|
||||
"pattern": "^[A-K]\\d{1,2}$"
|
||||
}
|
||||
"esc_output": {"$ref": "qmk.definitions.v1#/mcu_pin"},
|
||||
"esc_input": {"$ref": "qmk.definitions.v1#/mcu_pin"},
|
||||
"led": {"$ref": "qmk.definitions.v1#/mcu_pin"},
|
||||
"speaker": {"$ref": "qmk.definitions.v1#/mcu_pin"}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,143 @@
|
|||
{
|
||||
"keyboard_name": "nop60",
|
||||
"url": "",
|
||||
"maintainer": "nasp",
|
||||
"width": 15,
|
||||
"height": 5,
|
||||
"width": 15,
|
||||
"url": "",
|
||||
"layouts": {
|
||||
"LAYOUT": {
|
||||
"2x3u": [{"label":"Esc", "x":0, "y":0}, {"label":"!", "x":1, "y":0}, {"label":"@", "x":2, "y":0}, {"label":"#", "x":3, "y":0}, {"label":"$", "x":4, "y":0}, {"label":"%", "x":5, "y":0}, {"label":"^", "x":6, "y":0}, {"label":"&", "x":7, "y":0}, {"label":"*", "x":8, "y":0}, {"label":"(", "x":9, "y":0}, {"label":")", "x":10, "y":0}, {"label":"_", "x":11, "y":0}, {"label":"+", "x":12, "y":0}, {"label":"~", "x":13, "y":0}, {"label":"Bksp", "x":14, "y":0}, {"label":"Tab", "x":0, "y":1, "w":1.5}, {"label":"Q", "x":1.5, "y":1}, {"label":"W", "x":2.5, "y":1}, {"label":"E", "x":3.5, "y":1}, {"label":"R", "x":4.5, "y":1}, {"label":"T", "x":5.5, "y":1}, {"label":"Y", "x":6.5, "y":1}, {"label":"U", "x":7.5, "y":1}, {"label":"I", "x":8.5, "y":1}, {"label":"O", "x":9.5, "y":1}, {"label":"P", "x":10.5, "y":1}, {"label":"{", "x":11.5, "y":1}, {"label":"}", "x":12.5, "y":1}, {"label":"|", "x":13.5, "y":1, "w":1.5}, {"label":"Caps Lock", "x":0, "y":2, "w":1.75}, {"label":"A", "x":1.75, "y":2}, {"label":"S", "x":2.75, "y":2}, {"label":"D", "x":3.75, "y":2}, {"label":"F", "x":4.75, "y":2}, {"label":"G", "x":5.75, "y":2}, {"label":"H", "x":6.75, "y":2}, {"label":"J", "x":7.75, "y":2}, {"label":"K", "x":8.75, "y":2}, {"label":"L", "x":9.75, "y":2}, {"label":":", "x":10.75, "y":2}, {"label":"\"", "x":11.75, "y":2}, {"label":"Enter", "x":12.75, "y":2, "w":2.25}, {"label":"Shift", "x":0, "y":3, "w":2.25}, {"label":"Z", "x":2.25, "y":3}, {"label":"X", "x":3.25, "y":3}, {"label":"C", "x":4.25, "y":3}, {"label":"V", "x":5.25, "y":3}, {"label":"B", "x":6.25, "y":3}, {"label":"N", "x":7.25, "y":3}, {"label":"M", "x":8.25, "y":3}, {"label":"<", "x":9.25, "y":3}, {"label":">", "x":10.25, "y":3}, {"label":"?", "x":11.25, "y":3}, {"label":"Shift", "x":12.25, "y":3, "w":1.75}, {"label":"Fn", "x":14, "y":3}, {"label":"Ctrl", "x":0, "y":4, "w":1.5}, {"label":"Win", "x":1.5, "y":4}, {"label":"Alt", "x":2.5, "y":4, "w":1.5}, {"x":4, "y":4, "w":3}, {"x":7, "y":4}, {"x":8, "y":4, "w":3}, {"label":"Alt", "x":11, "y":4, "w":1.5}, {"label":"Win", "x":12.5, "y":4}, {"label":"Ctrl", "x":13.5, "y":4, "w":1.5}]
|
||||
"layout": [
|
||||
{ "label": "Esc", "x": 0, "y": 0 },
|
||||
{ "label": "!", "x": 1, "y": 0 },
|
||||
{ "label": "@", "x": 2, "y": 0 },
|
||||
{ "label": "#", "x": 3, "y": 0 },
|
||||
{ "label": "$", "x": 4, "y": 0 },
|
||||
{ "label": "%", "x": 5, "y": 0 },
|
||||
{ "label": "^", "x": 6, "y": 0 },
|
||||
{ "label": "&", "x": 7, "y": 0 },
|
||||
{ "label": "*", "x": 8, "y": 0 },
|
||||
{ "label": "(", "x": 9, "y": 0 },
|
||||
{ "label": ")", "x": 10, "y": 0 },
|
||||
{ "label": "_", "x": 11, "y": 0 },
|
||||
{ "label": "+", "x": 12, "y": 0 },
|
||||
{ "label": "~", "x": 13, "y": 0 },
|
||||
{ "label": "Bksp", "x": 14, "y": 0 },
|
||||
{ "label": "Tab", "w": 1.5, "x": 0, "y": 1 },
|
||||
{ "label": "Q", "x": 1.5, "y": 1 },
|
||||
{ "label": "W", "x": 2.5, "y": 1 },
|
||||
{ "label": "E", "x": 3.5, "y": 1 },
|
||||
{ "label": "R", "x": 4.5, "y": 1 },
|
||||
{ "label": "T", "x": 5.5, "y": 1 },
|
||||
{ "label": "Y", "x": 6.5, "y": 1 },
|
||||
{ "label": "U", "x": 7.5, "y": 1 },
|
||||
{ "label": "I", "x": 8.5, "y": 1 },
|
||||
{ "label": "O", "x": 9.5, "y": 1 },
|
||||
{ "label": "P", "x": 10.5, "y": 1 },
|
||||
{ "label": "{", "x": 11.5, "y": 1 },
|
||||
{ "label": "}", "x": 12.5, "y": 1 },
|
||||
{ "label": "|", "w": 1.5, "x": 13.5, "y": 1 },
|
||||
{ "label": "Caps Lock", "w": 1.75, "x": 0, "y": 2 },
|
||||
{ "label": "A", "x": 1.75, "y": 2 },
|
||||
{ "label": "S", "x": 2.75, "y": 2 },
|
||||
{ "label": "D", "x": 3.75, "y": 2 },
|
||||
{ "label": "F", "x": 4.75, "y": 2 },
|
||||
{ "label": "G", "x": 5.75, "y": 2 },
|
||||
{ "label": "H", "x": 6.75, "y": 2 },
|
||||
{ "label": "J", "x": 7.75, "y": 2 },
|
||||
{ "label": "K", "x": 8.75, "y": 2 },
|
||||
{ "label": "L", "x": 9.75, "y": 2 },
|
||||
{ "label": ":", "x": 10.75, "y": 2 },
|
||||
{ "label": "\"", "x": 11.75, "y": 2 },
|
||||
{ "label": "Enter", "w": 2.25, "x": 12.75, "y": 2 },
|
||||
{ "label": "Shift", "w": 2.25, "x": 0, "y": 3 },
|
||||
{ "label": "Z", "x": 2.25, "y": 3 },
|
||||
{ "label": "X", "x": 3.25, "y": 3 },
|
||||
{ "label": "C", "x": 4.25, "y": 3 },
|
||||
{ "label": "V", "x": 5.25, "y": 3 },
|
||||
{ "label": "B", "x": 6.25, "y": 3 },
|
||||
{ "label": "N", "x": 7.25, "y": 3 },
|
||||
{ "label": "M", "x": 8.25, "y": 3 },
|
||||
{ "label": "<", "x": 9.25, "y": 3 },
|
||||
{ "label": ">", "x": 10.25, "y": 3 },
|
||||
{ "label": "?", "x": 11.25, "y": 3 },
|
||||
{ "label": "Shift", "w": 1.75, "x": 12.25, "y": 3 },
|
||||
{ "label": "Fn", "x": 14, "y": 3 },
|
||||
{ "label": "Ctrl", "w": 1.5, "x": 0, "y": 4 },
|
||||
{ "label": "Win", "x": 1.5, "y": 4 },
|
||||
{ "label": "Alt", "w": 1.5, "x": 2.5, "y": 4 },
|
||||
{ "w": 7, "x": 4, "y": 4 },
|
||||
{ "label": "Alt", "w": 1.5, "x": 11, "y": 4 },
|
||||
{ "label": "Win", "x": 12.5, "y": 4 },
|
||||
{ "label": "Ctrl", "w": 1.5, "x": 13.5, "y": 4 }
|
||||
]
|
||||
},
|
||||
"LAYOUT": {
|
||||
"7u": [{"label":"Esc", "x":0, "y":0}, {"label":"!", "x":1, "y":0}, {"label":"@", "x":2, "y":0}, {"label":"#", "x":3, "y":0}, {"label":"$", "x":4, "y":0}, {"label":"%", "x":5, "y":0}, {"label":"^", "x":6, "y":0}, {"label":"&", "x":7, "y":0}, {"label":"*", "x":8, "y":0}, {"label":"(", "x":9, "y":0}, {"label":")", "x":10, "y":0}, {"label":"_", "x":11, "y":0}, {"label":"+", "x":12, "y":0}, {"label":"~", "x":13, "y":0}, {"label":"Bksp", "x":14, "y":0}, {"label":"Tab", "x":0, "y":1, "w":1.5}, {"label":"Q", "x":1.5, "y":1}, {"label":"W", "x":2.5, "y":1}, {"label":"E", "x":3.5, "y":1}, {"label":"R", "x":4.5, "y":1}, {"label":"T", "x":5.5, "y":1}, {"label":"Y", "x":6.5, "y":1}, {"label":"U", "x":7.5, "y":1}, {"label":"I", "x":8.5, "y":1}, {"label":"O", "x":9.5, "y":1}, {"label":"P", "x":10.5, "y":1}, {"label":"{", "x":11.5, "y":1}, {"label":"}", "x":12.5, "y":1}, {"label":"|", "x":13.5, "y":1, "w":1.5}, {"label":"Caps Lock", "x":0, "y":2, "w":1.75}, {"label":"A", "x":1.75, "y":2}, {"label":"S", "x":2.75, "y":2}, {"label":"D", "x":3.75, "y":2}, {"label":"F", "x":4.75, "y":2}, {"label":"G", "x":5.75, "y":2}, {"label":"H", "x":6.75, "y":2}, {"label":"J", "x":7.75, "y":2}, {"label":"K", "x":8.75, "y":2}, {"label":"L", "x":9.75, "y":2}, {"label":":", "x":10.75, "y":2}, {"label":"\"", "x":11.75, "y":2}, {"label":"Enter", "x":12.75, "y":2, "w":2.25}, {"label":"Shift", "x":0, "y":3, "w":2.25}, {"label":"Z", "x":2.25, "y":3}, {"label":"X", "x":3.25, "y":3}, {"label":"C", "x":4.25, "y":3}, {"label":"V", "x":5.25, "y":3}, {"label":"B", "x":6.25, "y":3}, {"label":"N", "x":7.25, "y":3}, {"label":"M", "x":8.25, "y":3}, {"label":"<", "x":9.25, "y":3}, {"label":">", "x":10.25, "y":3}, {"label":"?", "x":11.25, "y":3}, {"label":"Shift", "x":12.25, "y":3, "w":1.75}, {"label":"Fn", "x":14, "y":3}, {"label":"Ctrl", "x":0, "y":4, "w":1.5}, {"label":"Win", "x":1.5, "y":4}, {"label":"Alt", "x":2.5, "y":4, "w":1.5}, {"x":4, "y":4, "w":7}, {"label":"Alt", "x":11, "y":4, "w":1.5}, {"label":"Win", "x":12.5, "y":4}, {"label":"Ctrl", "x":13.5, "y":4, "w":1.5}]
|
||||
"LAYOUT_2x3u": {
|
||||
"layout": [
|
||||
{ "label": "Esc", "x": 0, "y": 0 },
|
||||
{ "label": "!", "x": 1, "y": 0 },
|
||||
{ "label": "@", "x": 2, "y": 0 },
|
||||
{ "label": "#", "x": 3, "y": 0 },
|
||||
{ "label": "$", "x": 4, "y": 0 },
|
||||
{ "label": "%", "x": 5, "y": 0 },
|
||||
{ "label": "^", "x": 6, "y": 0 },
|
||||
{ "label": "&", "x": 7, "y": 0 },
|
||||
{ "label": "*", "x": 8, "y": 0 },
|
||||
{ "label": "(", "x": 9, "y": 0 },
|
||||
{ "label": ")", "x": 10, "y": 0 },
|
||||
{ "label": "_", "x": 11, "y": 0 },
|
||||
{ "label": "+", "x": 12, "y": 0 },
|
||||
{ "label": "~", "x": 13, "y": 0 },
|
||||
{ "label": "Bksp", "x": 14, "y": 0 },
|
||||
{ "label": "Tab", "w": 1.5, "x": 0, "y": 1 },
|
||||
{ "label": "Q", "x": 1.5, "y": 1 },
|
||||
{ "label": "W", "x": 2.5, "y": 1 },
|
||||
{ "label": "E", "x": 3.5, "y": 1 },
|
||||
{ "label": "R", "x": 4.5, "y": 1 },
|
||||
{ "label": "T", "x": 5.5, "y": 1 },
|
||||
{ "label": "Y", "x": 6.5, "y": 1 },
|
||||
{ "label": "U", "x": 7.5, "y": 1 },
|
||||
{ "label": "I", "x": 8.5, "y": 1 },
|
||||
{ "label": "O", "x": 9.5, "y": 1 },
|
||||
{ "label": "P", "x": 10.5, "y": 1 },
|
||||
{ "label": "{", "x": 11.5, "y": 1 },
|
||||
{ "label": "}", "x": 12.5, "y": 1 },
|
||||
{ "label": "|", "w": 1.5, "x": 13.5, "y": 1 },
|
||||
{ "label": "Caps Lock", "w": 1.75, "x": 0, "y": 2 },
|
||||
{ "label": "A", "x": 1.75, "y": 2 },
|
||||
{ "label": "S", "x": 2.75, "y": 2 },
|
||||
{ "label": "D", "x": 3.75, "y": 2 },
|
||||
{ "label": "F", "x": 4.75, "y": 2 },
|
||||
{ "label": "G", "x": 5.75, "y": 2 },
|
||||
{ "label": "H", "x": 6.75, "y": 2 },
|
||||
{ "label": "J", "x": 7.75, "y": 2 },
|
||||
{ "label": "K", "x": 8.75, "y": 2 },
|
||||
{ "label": "L", "x": 9.75, "y": 2 },
|
||||
{ "label": ":", "x": 10.75, "y": 2 },
|
||||
{ "label": "\"", "x": 11.75, "y": 2 },
|
||||
{ "label": "Enter", "w": 2.25, "x": 12.75, "y": 2 },
|
||||
{ "label": "Shift", "w": 2.25, "x": 0, "y": 3 },
|
||||
{ "label": "Z", "x": 2.25, "y": 3 },
|
||||
{ "label": "X", "x": 3.25, "y": 3 },
|
||||
{ "label": "C", "x": 4.25, "y": 3 },
|
||||
{ "label": "V", "x": 5.25, "y": 3 },
|
||||
{ "label": "B", "x": 6.25, "y": 3 },
|
||||
{ "label": "N", "x": 7.25, "y": 3 },
|
||||
{ "label": "M", "x": 8.25, "y": 3 },
|
||||
{ "label": "<", "x": 9.25, "y": 3 },
|
||||
{ "label": ">", "x": 10.25, "y": 3 },
|
||||
{ "label": "?", "x": 11.25, "y": 3 },
|
||||
{ "label": "Shift", "w": 1.75, "x": 12.25, "y": 3 },
|
||||
{ "label": "Fn", "x": 14, "y": 3 },
|
||||
{ "label": "Ctrl", "w": 1.5, "x": 0, "y": 4 },
|
||||
{ "label": "Win", "x": 1.5, "y": 4 },
|
||||
{ "label": "Alt", "w": 1.5, "x": 2.5, "y": 4 },
|
||||
{ "w": 3, "x": 4, "y": 4 },
|
||||
{ "x": 7, "y": 4 },
|
||||
{ "w": 3, "x": 8, "y": 4 },
|
||||
{ "label": "Alt", "w": 1.5, "x": 11, "y": 4 },
|
||||
{ "label": "Win", "x": 12.5, "y": 4 },
|
||||
{ "label": "Ctrl", "w": 1.5, "x": 13.5, "y": 4 }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
{
|
||||
"keyboard_name": "Chevron",
|
||||
"url": "",
|
||||
"maintainer": "",
|
||||
"width": 14.5,
|
||||
"height": 5,
|
||||
"layouts": {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
"layouts": {
|
||||
"LAYOUT_ortho_5x15": {
|
||||
"layout": [
|
||||
{"label": "Esc", "X": 0, "y": 0},
|
||||
{"label": "Esc", "x": 0, "y": 0},
|
||||
{"label": "1", "x": 1, "y": 0},
|
||||
{"label": "2", "x": 2, "y": 0},
|
||||
{"label": "3", "x": 3, "y": 0},
|
||||
|
@ -22,21 +22,21 @@
|
|||
{"label": "NumLock", "x": 12, "y": 0},
|
||||
{"label": "/", "x": 13, "y": 0},
|
||||
{"label": "*", "x": 14, "y": 0},
|
||||
{"label": "Tab", "X": 0, "y": 1},
|
||||
{"label": "Q", "X": 1, "y": 1},
|
||||
{"label": "W", "X": 2, "y": 1},
|
||||
{"label": "E", "X": 3, "y": 1},
|
||||
{"label": "R", "X": 4, "y": 1},
|
||||
{"label": "T", "X": 5, "y": 1},
|
||||
{"label": "Y", "X": 6, "y": 1},
|
||||
{"label": "U", "X": 7, "y": 1},
|
||||
{"label": "I", "X": 8, "y": 1},
|
||||
{"label": "O", "X": 9, "y": 1},
|
||||
{"label": "P", "X": 10, "y": 1},
|
||||
{"label": "|\n\\", "X": 11, "y": 1},
|
||||
{"label": "7\nHome", "X": 12, "y": 1},
|
||||
{"label": "8\nUp", "X": 13, "y": 1},
|
||||
{"label": "9\nPgUp", "X": 14, "y": 1},
|
||||
{"label": "Tab", "x": 0, "y": 1},
|
||||
{"label": "Q", "x": 1, "y": 1},
|
||||
{"label": "W", "x": 2, "y": 1},
|
||||
{"label": "E", "x": 3, "y": 1},
|
||||
{"label": "R", "x": 4, "y": 1},
|
||||
{"label": "T", "x": 5, "y": 1},
|
||||
{"label": "Y", "x": 6, "y": 1},
|
||||
{"label": "U", "x": 7, "y": 1},
|
||||
{"label": "I", "x": 8, "y": 1},
|
||||
{"label": "O", "x": 9, "y": 1},
|
||||
{"label": "P", "x": 10, "y": 1},
|
||||
{"label": "|\n\\", "x": 11, "y": 1},
|
||||
{"label": "7\nHome", "x": 12, "y": 1},
|
||||
{"label": "8\nUp", "x": 13, "y": 1},
|
||||
{"label": "9\nPgUp", "x": 14, "y": 1},
|
||||
{"label": "Caps", "x": 0, "y": 2},
|
||||
{"label": "A", "x": 1, "y": 2},
|
||||
{"label": "S", "x": 2, "y": 2},
|
||||
|
@ -67,21 +67,21 @@
|
|||
{"label": "1\nEnd", "x": 12, "y": 3},
|
||||
{"label": "2\nDown", "x": 13, "y": 3},
|
||||
{"label": "3\nPgDn", "x": 14, "y": 3},
|
||||
{"label": "Ctrl", "X": 0, "y": 4},
|
||||
{"label": "Win", "X": 1, "y": 4},
|
||||
{"label": "Alt", "X": 2, "y": 4},
|
||||
{"label": "Fn", "X": 3, "y": 4},
|
||||
{"label": "Lower", "X": 4, "y": 4},
|
||||
{"label": "Space", "X": 5, "y": 4},
|
||||
{"label": "Space", "X": 6, "y": 4},
|
||||
{"label": "Raise", "X": 7, "y": 4},
|
||||
{"label": "Alt", "X": 8, "y": 4},
|
||||
{"label": "Win", "X": 9, "y": 4},
|
||||
{"label": "Menu", "X": 10, "y": 4},
|
||||
{"label": "Ctrl", "X": 11, "y": 4},
|
||||
{"label": "0\nIns", "X": 12, "y": 4},
|
||||
{"label": ".\nDel", "X": 13, "y": 4},
|
||||
{"label": "Enter", "X": 14, "y": 4}
|
||||
{"label": "Ctrl", "x": 0, "y": 4},
|
||||
{"label": "Win", "x": 1, "y": 4},
|
||||
{"label": "Alt", "x": 2, "y": 4},
|
||||
{"label": "Fn", "x": 3, "y": 4},
|
||||
{"label": "Lower", "x": 4, "y": 4},
|
||||
{"label": "Space", "x": 5, "y": 4},
|
||||
{"label": "Space", "x": 6, "y": 4},
|
||||
{"label": "Raise", "x": 7, "y": 4},
|
||||
{"label": "Alt", "x": 8, "y": 4},
|
||||
{"label": "Win", "x": 9, "y": 4},
|
||||
{"label": "Menu", "x": 10, "y": 4},
|
||||
{"label": "Ctrl", "x": 11, "y": 4},
|
||||
{"label": "0\nIns", "x": 12, "y": 4},
|
||||
{"label": ".\nDel", "x": 13, "y": 4},
|
||||
{"label": "Enter", "x": 14, "y": 4}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,10 @@ subcommands = [
|
|||
'qmk.cli.doctor',
|
||||
'qmk.cli.fileformat',
|
||||
'qmk.cli.flash',
|
||||
'qmk.cli.format.c',
|
||||
'qmk.cli.format.json',
|
||||
'qmk.cli.format.python',
|
||||
'qmk.cli.format.text',
|
||||
'qmk.cli.generate.api',
|
||||
'qmk.cli.generate.config_h',
|
||||
'qmk.cli.generate.dfu_header',
|
||||
|
|
139
lib/python/qmk/cli/cformat.py
Normal file → Executable file
139
lib/python/qmk/cli/cformat.py
Normal file → Executable file
|
@ -1,137 +1,28 @@
|
|||
"""Format C code according to QMK's style.
|
||||
"""Point people to the new command name.
|
||||
"""
|
||||
from os import path
|
||||
from shutil import which
|
||||
from subprocess import CalledProcessError, DEVNULL, Popen, PIPE
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from argcomplete.completers import FilesCompleter
|
||||
from milc import cli
|
||||
|
||||
from qmk.path import normpath
|
||||
from qmk.c_parse import c_source_files
|
||||
|
||||
c_file_suffixes = ('c', 'h', 'cpp')
|
||||
core_dirs = ('drivers', 'quantum', 'tests', 'tmk_core', 'platforms')
|
||||
ignored = ('tmk_core/protocol/usb_hid', 'quantum/template', 'platforms/chibios')
|
||||
|
||||
|
||||
def find_clang_format():
|
||||
"""Returns the path to clang-format.
|
||||
"""
|
||||
for clang_version in range(20, 6, -1):
|
||||
binary = f'clang-format-{clang_version}'
|
||||
|
||||
if which(binary):
|
||||
return binary
|
||||
|
||||
return 'clang-format'
|
||||
|
||||
|
||||
def find_diffs(files):
|
||||
"""Run clang-format and diff it against a file.
|
||||
"""
|
||||
found_diffs = False
|
||||
|
||||
for file in files:
|
||||
cli.log.debug('Checking for changes in %s', file)
|
||||
clang_format = Popen([find_clang_format(), file], stdout=PIPE, stderr=PIPE, universal_newlines=True)
|
||||
diff = cli.run(['diff', '-u', f'--label=a/{file}', f'--label=b/{file}', str(file), '-'], stdin=clang_format.stdout, capture_output=True)
|
||||
|
||||
if diff.returncode != 0:
|
||||
print(diff.stdout)
|
||||
found_diffs = True
|
||||
|
||||
return found_diffs
|
||||
|
||||
|
||||
def cformat_run(files):
|
||||
"""Spawn clang-format subprocess with proper arguments
|
||||
"""
|
||||
# Determine which version of clang-format to use
|
||||
clang_format = [find_clang_format(), '-i']
|
||||
|
||||
try:
|
||||
cli.run([*clang_format, *map(str, files)], check=True, capture_output=False, stdin=DEVNULL)
|
||||
cli.log.info('Successfully formatted the C code.')
|
||||
return True
|
||||
|
||||
except CalledProcessError as e:
|
||||
cli.log.error('Error formatting C code!')
|
||||
cli.log.debug('%s exited with returncode %s', e.cmd, e.returncode)
|
||||
cli.log.debug('STDOUT:')
|
||||
cli.log.debug(e.stdout)
|
||||
cli.log.debug('STDERR:')
|
||||
cli.log.debug(e.stderr)
|
||||
return False
|
||||
|
||||
|
||||
def filter_files(files, core_only=False):
|
||||
"""Yield only files to be formatted and skip the rest
|
||||
"""
|
||||
if core_only:
|
||||
# Filter non-core files
|
||||
for index, file in enumerate(files):
|
||||
# The following statement checks each file to see if the file path is
|
||||
# - in the core directories
|
||||
# - not in the ignored directories
|
||||
if not any(i in str(file) for i in core_dirs) or any(i in str(file) for i in ignored):
|
||||
files[index] = None
|
||||
cli.log.debug("Skipping non-core file %s, as '--core-only' is used.", file)
|
||||
|
||||
for file in files:
|
||||
if file and file.name.split('.')[-1] in c_file_suffixes:
|
||||
yield file
|
||||
else:
|
||||
cli.log.debug('Skipping file %s', file)
|
||||
|
||||
|
||||
@cli.argument('-n', '--dry-run', arg_only=True, action='store_true', help="Flag only, don't automatically format.")
|
||||
@cli.argument('-b', '--base-branch', default='origin/master', help='Branch to compare to diffs to.')
|
||||
@cli.argument('-a', '--all-files', arg_only=True, action='store_true', help='Format all core files.')
|
||||
@cli.argument('--core-only', arg_only=True, action='store_true', help='Format core files only.')
|
||||
@cli.argument('files', nargs='*', arg_only=True, type=normpath, completer=FilesCompleter('.c'), help='Filename(s) to format.')
|
||||
@cli.subcommand("Format C code according to QMK's style.", hidden=False if cli.config.user.developer else True)
|
||||
@cli.argument('files', nargs='*', arg_only=True, help='Filename(s) to format.')
|
||||
@cli.subcommand('Pointer to the new command name: qmk format-c.', hidden=False if cli.config.user.developer else True)
|
||||
def cformat(cli):
|
||||
"""Format C code according to QMK's style.
|
||||
"""Pointer to the new command name: qmk format-c.
|
||||
"""
|
||||
# Find the list of files to format
|
||||
if cli.args.files:
|
||||
files = list(filter_files(cli.args.files, cli.args.core_only))
|
||||
cli.log.warning('"qmk cformat" has been renamed to "qmk format-c". Please use the new command in the future.')
|
||||
argv = [sys.executable, *sys.argv]
|
||||
argv[argv.index('cformat')] = 'format-c'
|
||||
script_path = Path(argv[1])
|
||||
script_path_exe = Path(f'{argv[1]}.exe')
|
||||
|
||||
if not files:
|
||||
cli.log.error('No C files in filelist: %s', ', '.join(map(str, cli.args.files)))
|
||||
exit(0)
|
||||
if not script_path.exists() and script_path_exe.exists():
|
||||
# For reasons I don't understand ".exe" is stripped from the script name on windows.
|
||||
argv[1] = str(script_path_exe)
|
||||
|
||||
if cli.args.all_files:
|
||||
cli.log.warning('Filenames passed with -a, only formatting: %s', ','.join(map(str, files)))
|
||||
|
||||
elif cli.args.all_files:
|
||||
all_files = c_source_files(core_dirs)
|
||||
files = list(filter_files(all_files, True))
|
||||
|
||||
else:
|
||||
git_diff_cmd = ['git', 'diff', '--name-only', cli.args.base_branch, *core_dirs]
|
||||
git_diff = cli.run(git_diff_cmd, stdin=DEVNULL)
|
||||
|
||||
if git_diff.returncode != 0:
|
||||
cli.log.error("Error running %s", git_diff_cmd)
|
||||
print(git_diff.stderr)
|
||||
return git_diff.returncode
|
||||
|
||||
files = []
|
||||
|
||||
for file in git_diff.stdout.strip().split('\n'):
|
||||
if not any([file.startswith(ignore) for ignore in ignored]):
|
||||
if path.exists(file) and file.split('.')[-1] in c_file_suffixes:
|
||||
files.append(file)
|
||||
|
||||
# Sanity check
|
||||
if not files:
|
||||
cli.log.error('No changed files detected. Use "qmk cformat -a" to format all core files')
|
||||
return False
|
||||
|
||||
# Run clang-format on the files we've found
|
||||
if cli.args.dry_run:
|
||||
return not find_diffs(files)
|
||||
else:
|
||||
return cformat_run(files)
|
||||
return cli.run(argv, capture_output=False).returncode
|
||||
|
|
5
lib/python/qmk/cli/doctor/__init__.py
Executable file
5
lib/python/qmk/cli/doctor/__init__.py
Executable file
|
@ -0,0 +1,5 @@
|
|||
"""QMK Doctor
|
||||
|
||||
Check out the user's QMK environment and make sure it's ready to compile.
|
||||
"""
|
||||
from .main import doctor
|
|
@ -1,4 +1,4 @@
|
|||
"""OS-agnostic helper functions
|
||||
"""Check for specific programs.
|
||||
"""
|
||||
from enum import Enum
|
||||
import re
|
||||
|
@ -30,7 +30,7 @@ ESSENTIAL_BINARIES = {
|
|||
}
|
||||
|
||||
|
||||
def parse_gcc_version(version):
|
||||
def _parse_gcc_version(version):
|
||||
m = re.match(r"(\d+)(?:\.(\d+))?(?:\.(\d+))?", version)
|
||||
|
||||
return {
|
||||
|
@ -40,7 +40,7 @@ def parse_gcc_version(version):
|
|||
}
|
||||
|
||||
|
||||
def check_arm_gcc_version():
|
||||
def _check_arm_gcc_version():
|
||||
"""Returns True if the arm-none-eabi-gcc version is not known to cause problems.
|
||||
"""
|
||||
if 'output' in ESSENTIAL_BINARIES['arm-none-eabi-gcc']:
|
||||
|
@ -50,7 +50,7 @@ def check_arm_gcc_version():
|
|||
return CheckStatus.OK # Right now all known arm versions are ok
|
||||
|
||||
|
||||
def check_avr_gcc_version():
|
||||
def _check_avr_gcc_version():
|
||||
"""Returns True if the avr-gcc version is not known to cause problems.
|
||||
"""
|
||||
rc = CheckStatus.ERROR
|
||||
|
@ -60,7 +60,7 @@ def check_avr_gcc_version():
|
|||
cli.log.info('Found avr-gcc version %s', version_number)
|
||||
rc = CheckStatus.OK
|
||||
|
||||
parsed_version = parse_gcc_version(version_number)
|
||||
parsed_version = _parse_gcc_version(version_number)
|
||||
if parsed_version['major'] > 8:
|
||||
cli.log.warning('{fg_yellow}We do not recommend avr-gcc newer than 8. Downgrading to 8.x is recommended.')
|
||||
rc = CheckStatus.WARNING
|
||||
|
@ -68,7 +68,7 @@ def check_avr_gcc_version():
|
|||
return rc
|
||||
|
||||
|
||||
def check_avrdude_version():
|
||||
def _check_avrdude_version():
|
||||
if 'output' in ESSENTIAL_BINARIES['avrdude']:
|
||||
last_line = ESSENTIAL_BINARIES['avrdude']['output'].split('\n')[-2]
|
||||
version_number = last_line.split()[2][:-1]
|
||||
|
@ -77,7 +77,7 @@ def check_avrdude_version():
|
|||
return CheckStatus.OK
|
||||
|
||||
|
||||
def check_dfu_util_version():
|
||||
def _check_dfu_util_version():
|
||||
if 'output' in ESSENTIAL_BINARIES['dfu-util']:
|
||||
first_line = ESSENTIAL_BINARIES['dfu-util']['output'].split('\n')[0]
|
||||
version_number = first_line.split()[1]
|
||||
|
@ -86,7 +86,7 @@ def check_dfu_util_version():
|
|||
return CheckStatus.OK
|
||||
|
||||
|
||||
def check_dfu_programmer_version():
|
||||
def _check_dfu_programmer_version():
|
||||
if 'output' in ESSENTIAL_BINARIES['dfu-programmer']:
|
||||
first_line = ESSENTIAL_BINARIES['dfu-programmer']['output'].split('\n')[0]
|
||||
version_number = first_line.split()[1]
|
||||
|
@ -111,7 +111,7 @@ def check_binary_versions():
|
|||
"""Check the versions of ESSENTIAL_BINARIES
|
||||
"""
|
||||
versions = []
|
||||
for check in (check_arm_gcc_version, check_avr_gcc_version, check_avrdude_version, check_dfu_util_version, check_dfu_programmer_version):
|
||||
for check in (_check_arm_gcc_version, _check_avr_gcc_version, _check_avrdude_version, _check_dfu_util_version, _check_dfu_programmer_version):
|
||||
versions.append(check())
|
||||
return versions
|
||||
|
|
@ -1,11 +1,13 @@
|
|||
"""OS-specific functions for: Linux
|
||||
"""
|
||||
from pathlib import Path
|
||||
import platform
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
from milc import cli
|
||||
|
||||
from qmk.constants import QMK_FIRMWARE
|
||||
from qmk.os_helpers import CheckStatus
|
||||
from .check import CheckStatus
|
||||
|
||||
|
||||
def _udev_rule(vid, pid=None, *args):
|
||||
|
@ -138,3 +140,23 @@ def check_modem_manager():
|
|||
"""(TODO): Add check for non-systemd systems
|
||||
"""
|
||||
return False
|
||||
|
||||
|
||||
def os_test_linux():
|
||||
"""Run the Linux specific tests.
|
||||
"""
|
||||
# Don't bother with udev on WSL, for now
|
||||
if 'microsoft' in platform.uname().release.lower():
|
||||
cli.log.info("Detected {fg_cyan}Linux (WSL){fg_reset}.")
|
||||
|
||||
# https://github.com/microsoft/WSL/issues/4197
|
||||
if QMK_FIRMWARE.as_posix().startswith("/mnt"):
|
||||
cli.log.warning("I/O performance on /mnt may be extremely slow.")
|
||||
return CheckStatus.WARNING
|
||||
|
||||
return CheckStatus.OK
|
||||
else:
|
||||
cli.log.info("Detected {fg_cyan}Linux{fg_reset}.")
|
||||
from .linux import check_udev_rules
|
||||
|
||||
return check_udev_rules()
|
13
lib/python/qmk/cli/doctor/macos.py
Normal file
13
lib/python/qmk/cli/doctor/macos.py
Normal file
|
@ -0,0 +1,13 @@
|
|||
import platform
|
||||
|
||||
from milc import cli
|
||||
|
||||
from .check import CheckStatus
|
||||
|
||||
|
||||
def os_test_macos():
|
||||
"""Run the Mac specific tests.
|
||||
"""
|
||||
cli.log.info("Detected {fg_cyan}macOS %s{fg_reset}.", platform.mac_ver()[0])
|
||||
|
||||
return CheckStatus.OK
|
|
@ -7,9 +7,10 @@ from subprocess import DEVNULL
|
|||
|
||||
from milc import cli
|
||||
from milc.questions import yesno
|
||||
|
||||
from qmk import submodules
|
||||
from qmk.constants import QMK_FIRMWARE
|
||||
from qmk.os_helpers import CheckStatus, check_binaries, check_binary_versions, check_submodules, check_git_repo
|
||||
from .check import CheckStatus, check_binaries, check_binary_versions, check_submodules, check_git_repo
|
||||
|
||||
|
||||
def os_tests():
|
||||
|
@ -18,53 +19,19 @@ def os_tests():
|
|||
platform_id = platform.platform().lower()
|
||||
|
||||
if 'darwin' in platform_id or 'macos' in platform_id:
|
||||
from .macos import os_test_macos
|
||||
return os_test_macos()
|
||||
elif 'linux' in platform_id:
|
||||
from .linux import os_test_linux
|
||||
return os_test_linux()
|
||||
elif 'windows' in platform_id:
|
||||
from .windows import os_test_windows
|
||||
return os_test_windows()
|
||||
else:
|
||||
cli.log.warning('Unsupported OS detected: %s', platform_id)
|
||||
return CheckStatus.WARNING
|
||||
|
||||
|
||||
def os_test_linux():
|
||||
"""Run the Linux specific tests.
|
||||
"""
|
||||
# Don't bother with udev on WSL, for now
|
||||
if 'microsoft' in platform.uname().release.lower():
|
||||
cli.log.info("Detected {fg_cyan}Linux (WSL){fg_reset}.")
|
||||
|
||||
# https://github.com/microsoft/WSL/issues/4197
|
||||
if QMK_FIRMWARE.as_posix().startswith("/mnt"):
|
||||
cli.log.warning("I/O performance on /mnt may be extremely slow.")
|
||||
return CheckStatus.WARNING
|
||||
|
||||
return CheckStatus.OK
|
||||
else:
|
||||
cli.log.info("Detected {fg_cyan}Linux{fg_reset}.")
|
||||
from qmk.os_helpers.linux import check_udev_rules
|
||||
|
||||
return check_udev_rules()
|
||||
|
||||
|
||||
def os_test_macos():
|
||||
"""Run the Mac specific tests.
|
||||
"""
|
||||
cli.log.info("Detected {fg_cyan}macOS %s{fg_reset}.", platform.mac_ver()[0])
|
||||
|
||||
return CheckStatus.OK
|
||||
|
||||
|
||||
def os_test_windows():
|
||||
"""Run the Windows specific tests.
|
||||
"""
|
||||
win32_ver = platform.win32_ver()
|
||||
cli.log.info("Detected {fg_cyan}Windows %s (%s){fg_reset}.", win32_ver[0], win32_ver[1])
|
||||
|
||||
return CheckStatus.OK
|
||||
|
||||
|
||||
@cli.argument('-y', '--yes', action='store_true', arg_only=True, help='Answer yes to all questions.')
|
||||
@cli.argument('-n', '--no', action='store_true', arg_only=True, help='Answer no to all questions.')
|
||||
@cli.subcommand('Basic QMK environment checks')
|
14
lib/python/qmk/cli/doctor/windows.py
Normal file
14
lib/python/qmk/cli/doctor/windows.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
import platform
|
||||
|
||||
from milc import cli
|
||||
|
||||
from .check import CheckStatus
|
||||
|
||||
|
||||
def os_test_windows():
|
||||
"""Run the Windows specific tests.
|
||||
"""
|
||||
win32_ver = platform.win32_ver()
|
||||
cli.log.info("Detected {fg_cyan}Windows %s (%s){fg_reset}.", win32_ver[0], win32_ver[1])
|
||||
|
||||
return CheckStatus.OK
|
24
lib/python/qmk/cli/fileformat.py
Normal file → Executable file
24
lib/python/qmk/cli/fileformat.py
Normal file → Executable file
|
@ -1,13 +1,23 @@
|
|||
"""Format files according to QMK's style.
|
||||
"""Point people to the new command name.
|
||||
"""
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from milc import cli
|
||||
|
||||
import subprocess
|
||||
|
||||
|
||||
@cli.subcommand("Format files according to QMK's style.", hidden=True)
|
||||
@cli.subcommand('Pointer to the new command name: qmk format-text.', hidden=False if cli.config.user.developer else True)
|
||||
def fileformat(cli):
|
||||
"""Run several general formatting commands.
|
||||
"""Pointer to the new command name: qmk format-text.
|
||||
"""
|
||||
dos2unix = subprocess.run(['bash', '-c', 'git ls-files -z | xargs -0 dos2unix'], stdout=subprocess.DEVNULL)
|
||||
return dos2unix.returncode
|
||||
cli.log.warning('"qmk fileformat" has been renamed to "qmk format-text". Please use the new command in the future.')
|
||||
argv = [sys.executable, *sys.argv]
|
||||
argv[argv.index('fileformat')] = 'format-text'
|
||||
script_path = Path(argv[1])
|
||||
script_path_exe = Path(f'{argv[1]}.exe')
|
||||
|
||||
if not script_path.exists() and script_path_exe.exists():
|
||||
# For reasons I don't understand ".exe" is stripped from the script name on windows.
|
||||
argv[1] = str(script_path_exe)
|
||||
|
||||
return cli.run(argv, capture_output=False).returncode
|
||||
|
|
137
lib/python/qmk/cli/format/c.py
Normal file
137
lib/python/qmk/cli/format/c.py
Normal file
|
@ -0,0 +1,137 @@
|
|||
"""Format C code according to QMK's style.
|
||||
"""
|
||||
from os import path
|
||||
from shutil import which
|
||||
from subprocess import CalledProcessError, DEVNULL, Popen, PIPE
|
||||
|
||||
from argcomplete.completers import FilesCompleter
|
||||
from milc import cli
|
||||
|
||||
from qmk.path import normpath
|
||||
from qmk.c_parse import c_source_files
|
||||
|
||||
c_file_suffixes = ('c', 'h', 'cpp')
|
||||
core_dirs = ('drivers', 'quantum', 'tests', 'tmk_core', 'platforms')
|
||||
ignored = ('tmk_core/protocol/usb_hid', 'quantum/template', 'platforms/chibios')
|
||||
|
||||
|
||||
def find_clang_format():
|
||||
"""Returns the path to clang-format.
|
||||
"""
|
||||
for clang_version in range(20, 6, -1):
|
||||
binary = f'clang-format-{clang_version}'
|
||||
|
||||
if which(binary):
|
||||
return binary
|
||||
|
||||
return 'clang-format'
|
||||
|
||||
|
||||
def find_diffs(files):
|
||||
"""Run clang-format and diff it against a file.
|
||||
"""
|
||||
found_diffs = False
|
||||
|
||||
for file in files:
|
||||
cli.log.debug('Checking for changes in %s', file)
|
||||
clang_format = Popen([find_clang_format(), file], stdout=PIPE, stderr=PIPE, universal_newlines=True)
|
||||
diff = cli.run(['diff', '-u', f'--label=a/{file}', f'--label=b/{file}', str(file), '-'], stdin=clang_format.stdout, capture_output=True)
|
||||
|
||||
if diff.returncode != 0:
|
||||
print(diff.stdout)
|
||||
found_diffs = True
|
||||
|
||||
return found_diffs
|
||||
|
||||
|
||||
def cformat_run(files):
|
||||
"""Spawn clang-format subprocess with proper arguments
|
||||
"""
|
||||
# Determine which version of clang-format to use
|
||||
clang_format = [find_clang_format(), '-i']
|
||||
|
||||
try:
|
||||
cli.run([*clang_format, *map(str, files)], check=True, capture_output=False, stdin=DEVNULL)
|
||||
cli.log.info('Successfully formatted the C code.')
|
||||
return True
|
||||
|
||||
except CalledProcessError as e:
|
||||
cli.log.error('Error formatting C code!')
|
||||
cli.log.debug('%s exited with returncode %s', e.cmd, e.returncode)
|
||||
cli.log.debug('STDOUT:')
|
||||
cli.log.debug(e.stdout)
|
||||
cli.log.debug('STDERR:')
|
||||
cli.log.debug(e.stderr)
|
||||
return False
|
||||
|
||||
|
||||
def filter_files(files, core_only=False):
|
||||
"""Yield only files to be formatted and skip the rest
|
||||
"""
|
||||
if core_only:
|
||||
# Filter non-core files
|
||||
for index, file in enumerate(files):
|
||||
# The following statement checks each file to see if the file path is
|
||||
# - in the core directories
|
||||
# - not in the ignored directories
|
||||
if not any(i in str(file) for i in core_dirs) or any(i in str(file) for i in ignored):
|
||||
files[index] = None
|
||||
cli.log.debug("Skipping non-core file %s, as '--core-only' is used.", file)
|
||||
|
||||
for file in files:
|
||||
if file and file.name.split('.')[-1] in c_file_suffixes:
|
||||
yield file
|
||||
else:
|
||||
cli.log.debug('Skipping file %s', file)
|
||||
|
||||
|
||||
@cli.argument('-n', '--dry-run', arg_only=True, action='store_true', help="Flag only, don't automatically format.")
|
||||
@cli.argument('-b', '--base-branch', default='origin/master', help='Branch to compare to diffs to.')
|
||||
@cli.argument('-a', '--all-files', arg_only=True, action='store_true', help='Format all core files.')
|
||||
@cli.argument('--core-only', arg_only=True, action='store_true', help='Format core files only.')
|
||||
@cli.argument('files', nargs='*', arg_only=True, type=normpath, completer=FilesCompleter('.c'), help='Filename(s) to format.')
|
||||
@cli.subcommand("Format C code according to QMK's style.", hidden=False if cli.config.user.developer else True)
|
||||
def format_c(cli):
|
||||
"""Format C code according to QMK's style.
|
||||
"""
|
||||
# Find the list of files to format
|
||||
if cli.args.files:
|
||||
files = list(filter_files(cli.args.files, cli.args.core_only))
|
||||
|
||||
if not files:
|
||||
cli.log.error('No C files in filelist: %s', ', '.join(map(str, cli.args.files)))
|
||||
exit(0)
|
||||
|
||||
if cli.args.all_files:
|
||||
cli.log.warning('Filenames passed with -a, only formatting: %s', ','.join(map(str, files)))
|
||||
|
||||
elif cli.args.all_files:
|
||||
all_files = c_source_files(core_dirs)
|
||||
files = list(filter_files(all_files, True))
|
||||
|
||||
else:
|
||||
git_diff_cmd = ['git', 'diff', '--name-only', cli.args.base_branch, *core_dirs]
|
||||
git_diff = cli.run(git_diff_cmd, stdin=DEVNULL)
|
||||
|
||||
if git_diff.returncode != 0:
|
||||
cli.log.error("Error running %s", git_diff_cmd)
|
||||
print(git_diff.stderr)
|
||||
return git_diff.returncode
|
||||
|
||||
files = []
|
||||
|
||||
for file in git_diff.stdout.strip().split('\n'):
|
||||
if not any([file.startswith(ignore) for ignore in ignored]):
|
||||
if path.exists(file) and file.split('.')[-1] in c_file_suffixes:
|
||||
files.append(file)
|
||||
|
||||
# Sanity check
|
||||
if not files:
|
||||
cli.log.error('No changed files detected. Use "qmk cformat -a" to format all core files')
|
||||
return False
|
||||
|
||||
# Run clang-format on the files we've found
|
||||
if cli.args.dry_run:
|
||||
return not find_diffs(files)
|
||||
else:
|
||||
return cformat_run(files)
|
|
@ -8,7 +8,7 @@ from jsonschema import ValidationError
|
|||
from milc import cli
|
||||
|
||||
from qmk.info import info_json
|
||||
from qmk.json_schema import json_load, keyboard_validate
|
||||
from qmk.json_schema import json_load, validate
|
||||
from qmk.json_encoders import InfoJSONEncoder, KeymapJSONEncoder
|
||||
from qmk.path import normpath
|
||||
|
||||
|
@ -23,14 +23,13 @@ def format_json(cli):
|
|||
|
||||
if cli.args.format == 'auto':
|
||||
try:
|
||||
keyboard_validate(json_file)
|
||||
validate(json_file, 'qmk.keyboard.v1')
|
||||
json_encoder = InfoJSONEncoder
|
||||
|
||||
except ValidationError as e:
|
||||
cli.log.warning('File %s did not validate as a keyboard:\n\t%s', cli.args.json_file, e)
|
||||
cli.log.info('Treating %s as a keymap file.', cli.args.json_file)
|
||||
json_encoder = KeymapJSONEncoder
|
||||
|
||||
elif cli.args.format == 'keyboard':
|
||||
json_encoder = InfoJSONEncoder
|
||||
elif cli.args.format == 'keymap':
|
||||
|
|
26
lib/python/qmk/cli/format/python.py
Executable file
26
lib/python/qmk/cli/format/python.py
Executable file
|
@ -0,0 +1,26 @@
|
|||
"""Format python code according to QMK's style.
|
||||
"""
|
||||
from subprocess import CalledProcessError, DEVNULL
|
||||
|
||||
from milc import cli
|
||||
|
||||
|
||||
@cli.argument('-n', '--dry-run', arg_only=True, action='store_true', help="Don't actually format.")
|
||||
@cli.subcommand("Format python code according to QMK's style.", hidden=False if cli.config.user.developer else True)
|
||||
def format_python(cli):
|
||||
"""Format python code according to QMK's style.
|
||||
"""
|
||||
edit = '--diff' if cli.args.dry_run else '--in-place'
|
||||
yapf_cmd = ['yapf', '-vv', '--recursive', edit, 'bin/qmk', 'lib/python']
|
||||
try:
|
||||
cli.run(yapf_cmd, check=True, capture_output=False, stdin=DEVNULL)
|
||||
cli.log.info('Python code in `bin/qmk` and `lib/python` is correctly formatted.')
|
||||
return True
|
||||
|
||||
except CalledProcessError:
|
||||
if cli.args.dry_run:
|
||||
cli.log.error('Python code in `bin/qmk` and `lib/python` incorrectly formatted!')
|
||||
else:
|
||||
cli.log.error('Error formatting python code!')
|
||||
|
||||
return False
|
27
lib/python/qmk/cli/format/text.py
Normal file
27
lib/python/qmk/cli/format/text.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
"""Ensure text files have the proper line endings.
|
||||
"""
|
||||
from subprocess import CalledProcessError
|
||||
|
||||
from milc import cli
|
||||
|
||||
|
||||
@cli.subcommand("Ensure text files have the proper line endings.", hidden=True)
|
||||
def format_text(cli):
|
||||
"""Ensure text files have the proper line endings.
|
||||
"""
|
||||
try:
|
||||
file_list_cmd = cli.run(['git', 'ls-files', '-z'], check=True)
|
||||
except CalledProcessError as e:
|
||||
cli.log.error('Could not get file list: %s', e)
|
||||
exit(1)
|
||||
except Exception as e:
|
||||
cli.log.error('Unhandled exception: %s: %s', e.__class__.__name__, e)
|
||||
cli.log.exception(e)
|
||||
exit(1)
|
||||
|
||||
dos2unix = cli.run(['xargs', '-0', 'dos2unix'], stdin=None, input=file_list_cmd.stdout)
|
||||
|
||||
if dos2unix.returncode != 0:
|
||||
print(dos2unix.stderr)
|
||||
|
||||
return dos2unix.returncode
|
|
@ -1,26 +1,24 @@
|
|||
"""Format python code according to QMK's style.
|
||||
"""Point people to the new command name.
|
||||
"""
|
||||
from subprocess import CalledProcessError, DEVNULL
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from milc import cli
|
||||
|
||||
|
||||
@cli.argument('-n', '--dry-run', arg_only=True, action='store_true', help="Flag only, don't automatically format.")
|
||||
@cli.subcommand("Format python code according to QMK's style.", hidden=False if cli.config.user.developer else True)
|
||||
@cli.argument('-n', '--dry-run', arg_only=True, action='store_true', help="Don't actually format.")
|
||||
@cli.subcommand('Pointer to the new command name: qmk format-python.', hidden=False if cli.config.user.developer else True)
|
||||
def pyformat(cli):
|
||||
"""Format python code according to QMK's style.
|
||||
"""Pointer to the new command name: qmk format-python.
|
||||
"""
|
||||
edit = '--diff' if cli.args.dry_run else '--in-place'
|
||||
yapf_cmd = ['yapf', '-vv', '--recursive', edit, 'bin/qmk', 'lib/python']
|
||||
try:
|
||||
cli.run(yapf_cmd, check=True, capture_output=False, stdin=DEVNULL)
|
||||
cli.log.info('Python code in `bin/qmk` and `lib/python` is correctly formatted.')
|
||||
return True
|
||||
cli.log.warning('"qmk pyformat" has been renamed to "qmk format-python". Please use the new command in the future.')
|
||||
argv = [sys.executable, *sys.argv]
|
||||
argv[argv.index('pyformat')] = 'format-python'
|
||||
script_path = Path(argv[1])
|
||||
script_path_exe = Path(f'{argv[1]}.exe')
|
||||
|
||||
except CalledProcessError:
|
||||
if cli.args.dry_run:
|
||||
cli.log.error('Python code in `bin/qmk` and `lib/python` incorrectly formatted!')
|
||||
else:
|
||||
cli.log.error('Error formatting python code!')
|
||||
if not script_path.exists() and script_path_exe.exists():
|
||||
# For reasons I don't understand ".exe" is stripped from the script name on windows.
|
||||
argv[1] = str(script_path_exe)
|
||||
|
||||
return False
|
||||
return cli.run(argv, capture_output=False).returncode
|
||||
|
|
|
@ -9,7 +9,7 @@ from milc import cli
|
|||
|
||||
from qmk.constants import CHIBIOS_PROCESSORS, LUFA_PROCESSORS, VUSB_PROCESSORS
|
||||
from qmk.c_parse import find_layouts
|
||||
from qmk.json_schema import deep_update, json_load, keyboard_validate, keyboard_api_validate
|
||||
from qmk.json_schema import deep_update, json_load, validate
|
||||
from qmk.keyboard import config_h, rules_mk
|
||||
from qmk.keymap import list_keymaps
|
||||
from qmk.makefile import parse_rules_mk_file
|
||||
|
@ -66,7 +66,7 @@ def info_json(keyboard):
|
|||
|
||||
# Validate against the jsonschema
|
||||
try:
|
||||
keyboard_api_validate(info_data)
|
||||
validate(info_data, 'qmk.api.keyboard.v1')
|
||||
|
||||
except jsonschema.ValidationError as e:
|
||||
json_path = '.'.join([str(p) for p in e.absolute_path])
|
||||
|
@ -496,7 +496,7 @@ def merge_info_jsons(keyboard, info_data):
|
|||
continue
|
||||
|
||||
try:
|
||||
keyboard_validate(new_info_data)
|
||||
validate(new_info_data, 'qmk.keyboard.v1')
|
||||
except jsonschema.ValidationError as e:
|
||||
json_path = '.'.join([str(p) for p in e.absolute_path])
|
||||
cli.log.error('Not including data from file: %s', info_file)
|
||||
|
|
|
@ -24,9 +24,10 @@ def json_load(json_file):
|
|||
|
||||
def load_jsonschema(schema_name):
|
||||
"""Read a jsonschema file from disk.
|
||||
|
||||
FIXME(skullydazed/anyone): Refactor to make this a public function.
|
||||
"""
|
||||
if Path(schema_name).exists():
|
||||
return json_load(schema_name)
|
||||
|
||||
schema_path = Path(f'data/schemas/{schema_name}.jsonschema')
|
||||
|
||||
if not schema_path.exists():
|
||||
|
@ -35,28 +36,33 @@ def load_jsonschema(schema_name):
|
|||
return json_load(schema_path)
|
||||
|
||||
|
||||
def keyboard_validate(data):
|
||||
"""Validates data against the keyboard jsonschema.
|
||||
def create_validator(schema):
|
||||
"""Creates a validator for the given schema id.
|
||||
"""
|
||||
schema = load_jsonschema('keyboard')
|
||||
validator = jsonschema.Draft7Validator(schema).validate
|
||||
schema_store = {}
|
||||
|
||||
return validator(data)
|
||||
for schema_file in Path('data/schemas').glob('*.jsonschema'):
|
||||
schema_data = load_jsonschema(schema_file)
|
||||
if not isinstance(schema_data, dict):
|
||||
cli.log.debug('Skipping schema file %s', schema_file)
|
||||
continue
|
||||
schema_store[schema_data['$id']] = schema_data
|
||||
|
||||
resolver = jsonschema.RefResolver.from_schema(schema_store['qmk.keyboard.v1'], store=schema_store)
|
||||
|
||||
return jsonschema.Draft7Validator(schema_store[schema], resolver=resolver).validate
|
||||
|
||||
|
||||
def keyboard_api_validate(data):
|
||||
"""Validates data against the api_keyboard jsonschema.
|
||||
def validate(data, schema):
|
||||
"""Validates data against a schema.
|
||||
"""
|
||||
base = load_jsonschema('keyboard')
|
||||
relative = load_jsonschema('api_keyboard')
|
||||
resolver = jsonschema.RefResolver.from_schema(base)
|
||||
validator = jsonschema.Draft7Validator(relative, resolver=resolver).validate
|
||||
validator = create_validator(schema)
|
||||
|
||||
return validator(data)
|
||||
|
||||
|
||||
def deep_update(origdict, newdict):
|
||||
"""Update a dictionary in place, recursing to do a deep copy.
|
||||
"""Update a dictionary in place, recursing to do a depth-first deep copy.
|
||||
"""
|
||||
for key, value in newdict.items():
|
||||
if isinstance(value, Mapping):
|
||||
|
|
Loading…
Reference in a new issue