Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .ci/check-format.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/usr/bin/env bash

# The -e is not set because we want to get all the mismatch format at once

set -u -o pipefail

set -x

REPO_ROOT="$(git rev-parse --show-toplevel)"

SH_SOURCES=$(find "${REPO_ROOT}" | egrep "\.sh$")
for file in ${SH_SOURCES}; do
shfmt -d "${file}"
done
SH_MISMATCH_FILE_CNT=0
if [ -n "${SH_SOURCES}" ]; then
SH_MISMATCH_FILE_CNT=$(shfmt -l ${SH_SOURCES} | wc -l)
fi

PY_SOURCES=$(find "${REPO_ROOT}" | egrep "\.py$")
for file in ${PY_SOURCES}; do
echo "Checking Python file: ${file}"
black --diff "${file}"
done
PY_MISMATCH_FILE_CNT=0
if [ -n "${PY_SOURCES}" ]; then
PY_MISMATCH_FILE_CNT=$(echo "$(black --check ${PY_SOURCES} 2>&1)" | grep -c "^would reformat ")
fi

exit $((SH_MISMATCH_FILE_CNT + PY_MISMATCH_FILE_CNT))
19 changes: 19 additions & 0 deletions .ci/check-newline.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/env bash

set -e -u -o pipefail

ret=0
show=0
# Reference: https://medium.com/@alexey.inkin/how-to-force-newline-at-end-of-files-and-why-you-should-do-it-fdf76d1d090e
while IFS= read -rd '' f; do
if file --mime-encoding "$f" | grep -qv binary; then
tail -c1 <"$f" | read -r _ || show=1
if [ $show -eq 1 ]; then
echo "Warning: No newline at end of file $f"
ret=1
show=0
fi
fi
done < <(git ls-files -z '*.py' '*.sh' tests examples)

exit $ret
32 changes: 32 additions & 0 deletions .github/workflows/style.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Style Check

on: [push, pull_request]

concurrency:
group: style-check-${{ github.ref }}
cancel-in-progress: true

jobs:
format-check:
name: Check Code Format
runs-on: ubuntu-latest

steps:
- name: Check out Kconfiglib source code
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'

- name: Install tools
run: |
sudo apt-get install -q=2 shfmt python3-pip
pip3 install black==25.1.0

- name: Run format check
run: |
.ci/check-newline.sh
.ci/check-format.sh
shell: bash
60 changes: 60 additions & 0 deletions check_colors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/usr/bin/env python3
"""
檢查 menuconfig.py 的顏色設定是否符合 mconf
"""

import re

# 讀取 menuconfig.py 的顏色設定
with open("menuconfig.py", "r") as f:
content = f.read()

# 提取 _STYLES["default"]
match = re.search(r'_STYLES = \{[^}]*"default": """([^"]+)"""', content, re.DOTALL)
if match:
styles = match.group(1)
print("Kconfiglib 顏色設定:")
print("=" * 60)
for line in styles.strip().split("\n"):
line = line.strip()
if line:
print(f" {line}")
print()

# mconf 顏色對照表 (from util.c:61-89)
print("mconf bluetitle theme 對照:")
print("=" * 60)
mconf_colors = [
("screen", "CYAN", "BLUE", "bold"),
("dialog", "BLACK", "WHITE", ""),
("title", "YELLOW", "WHITE", "bold"),
("border", "WHITE", "WHITE", "bold"),
("button_active", "WHITE", "BLUE", "bold"),
("button_inactive", "BLACK", "WHITE", ""),
("item", "BLACK", "WHITE", ""),
("item_selected", "WHITE", "BLUE", "bold"),
("tag", "YELLOW", "WHITE", "bold"),
("uarrow/darrow", "GREEN", "WHITE", "bold"),
("menubox", "BLACK", "WHITE", ""),
("menubox_border", "WHITE", "WHITE", "bold"),
]

for name, fg, bg, attr in mconf_colors:
attr_str = f",{attr}" if attr else ""
print(f" {name:20s} = fg:{fg.lower()},bg:{bg.lower()}{attr_str}")

print()
print("對應關係:")
print("=" * 60)
mappings = [
("screen", "→", "螢幕背景 (_stdscr.bkgd)"),
("dialog/item", "→", "list (fg:black,bg:white)"),
("border", "→", "frame (fg:white,bg:white,bold)"),
("item_selected", "→", "selection (fg:white,bg:blue,bold)"),
("tag", "→", "path/help (fg:yellow,bg:white,bold)"),
("uarrow/darrow", "→", "arrow (fg:green,bg:white,bold)"),
("title", "→", "path (fg:yellow,bg:white,bold)"),
]

for mconf, arrow, kconfiglib in mappings:
print(f" {mconf:20s} {arrow} {kconfiglib}")
14 changes: 6 additions & 8 deletions defconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,16 @@

def main():
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description=__doc__)
formatter_class=argparse.RawDescriptionHelpFormatter, description=__doc__
)

parser.add_argument(
"--kconfig",
default="Kconfig",
help="Top-level Kconfig file (default: Kconfig)")
"--kconfig", default="Kconfig", help="Top-level Kconfig file (default: Kconfig)"
)

parser.add_argument(
"config",
metavar="CONFIGURATION",
help="Input configuration file")
"config", metavar="CONFIGURATION", help="Input configuration file"
)

args = parser.parse_args()

Expand Down
8 changes: 5 additions & 3 deletions examples/allnoconfig_walk.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@ def do_allnoconfig(node):

# Is the symbol a non-allnoconfig_y symbol that can be set to a
# lower value than its current value?
if (not sym.is_allnoconfig_y and
sym.assignable and
sym.assignable[0] < sym.tri_value):
if (
not sym.is_allnoconfig_y
and sym.assignable
and sym.assignable[0] < sym.tri_value
):

# Yup, lower it
sym.set_value(sym.assignable[0])
Expand Down
8 changes: 6 additions & 2 deletions examples/dumpvars.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,9 @@
import kconfiglib


print(" ".join("{}='{}'".format(var, os.environ[var])
for var in kconfiglib.Kconfig(sys.argv[1]).env_vars))
print(
" ".join(
"{}='{}'".format(var, os.environ[var])
for var in kconfiglib.Kconfig(sys.argv[1]).env_vars
)
)
3 changes: 1 addition & 2 deletions examples/eval_expr.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,4 @@
# Enable modules so that m doesn't get demoted to n
kconf.modules.set_value(2)

print("the expression '{}' evaluates to {}"
.format(expr, kconf.eval_string(expr)))
print("the expression '{}' evaluates to {}".format(expr, kconf.eval_string(expr)))
22 changes: 14 additions & 8 deletions examples/find_symbol.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,25 +88,31 @@
print("No symbol {} exists in the configuration".format(sym_name))
sys.exit(0)

referencing = [node for node in kconf.node_iter()
if kconf.syms[sym_name] in node.referenced]
referencing = [
node for node in kconf.node_iter() if kconf.syms[sym_name] in node.referenced
]
if not referencing:
print("No references to {} found".format(sym_name))
sys.exit(0)

print("Found {} locations that reference {}:\n"
.format(len(referencing), sym_name))
print("Found {} locations that reference {}:\n".format(len(referencing), sym_name))

for i, node in enumerate(referencing, 1):
print("========== Location {} ({}:{}) ==========\n\n{}"
.format(i, node.filename, node.linenr, node))
print(
"========== Location {} ({}:{}) ==========\n\n{}".format(
i, node.filename, node.linenr, node
)
)

# Print the parents of the menu node too

node = node.parent
parent_i = 1
while node is not kconf.top_node:
print("---------- Parent {} ({}:{}) ----------\n\n{}"
.format(parent_i, node.filename, node.linenr, node))
print(
"---------- Parent {} ({}:{}) ----------\n\n{}".format(
parent_i, node.filename, node.linenr, node
)
)
node = node.parent
parent_i += 1
7 changes: 5 additions & 2 deletions examples/help_grep.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,11 @@
for node in Kconfig(sys.argv[1]).node_iter():
match = False

if isinstance(node.item, (Symbol, Choice)) and \
node.help is not None and search(node.help):
if (
isinstance(node.item, (Symbol, Choice))
and node.help is not None
and search(node.help)
):
print(node.item)
match = True

Expand Down
12 changes: 7 additions & 5 deletions examples/list_undefined.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,7 @@ def all_arch_srcarch_kconfigs():
os.environ["SRCARCH"] = srcarch

# um (User Mode Linux) uses a different base Kconfig file
yield Kconfig("Kconfig" if arch != "um" else "arch/x86/um/Kconfig",
warn=False)
yield Kconfig("Kconfig" if arch != "um" else "arch/x86/um/Kconfig", warn=False)


print("Registering defined and undefined symbols for all arches")
Expand Down Expand Up @@ -122,6 +121,7 @@ def all_arch_srcarch_kconfigs():

print("\nFinding references to each undefined symbol")


def referencing_nodes(kconf, name):
# Returns a list of all menu nodes that reference a symbol named 'name' in
# any of their properties or property conditions
Expand All @@ -148,9 +148,11 @@ def referencing_nodes(kconf, name):
refs.add("{}:{}".format(node.filename, node.linenr))


print("\nThe following globally undefined symbols were found, listed here\n"
"together with the locations of the items that reference them.\n"
"References might come from enclosing menus and ifs.\n")
print(
"\nThe following globally undefined symbols were found, listed here\n"
"together with the locations of the items that reference them.\n"
"References might come from enclosing menus and ifs.\n"
)

for name, refs in undef_sym_refs:
print(" {}: {}".format(name, ", ".join(refs)))
38 changes: 26 additions & 12 deletions examples/menuconfig_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,20 @@
import readline
import sys

from kconfiglib import Kconfig, \
Symbol, MENU, COMMENT, \
BOOL, TRISTATE, STRING, INT, HEX, UNKNOWN, \
expr_value, \
TRI_TO_STR
from kconfiglib import (
Kconfig,
Symbol,
MENU,
COMMENT,
BOOL,
TRISTATE,
STRING,
INT,
HEX,
UNKNOWN,
expr_value,
TRI_TO_STR,
)


# Python 2/3 compatibility hack
Expand All @@ -136,7 +145,7 @@


def indent_print(s, indent):
print(indent*" " + s)
print(indent * " " + s)


def value_str(sc):
Expand Down Expand Up @@ -264,8 +273,9 @@ def get_value_from_user(sc):

prompt = "Value for {}".format(sc.name)
if sc.type in (BOOL, TRISTATE):
prompt += " (available: {})" \
.format(", ".join(TRI_TO_STR[val] for val in sc.assignable))
prompt += " (available: {})".format(
", ".join(TRI_TO_STR[val] for val in sc.assignable)
)
prompt += ": "

val = input(prompt)
Expand Down Expand Up @@ -294,8 +304,10 @@ def get_value_from_user(sc):

while True:
try:
cmd = input('Enter a symbol/choice name, "load_config", or '
'"write_config" (or press CTRL+D to exit): ').strip()
cmd = input(
'Enter a symbol/choice name, "load_config", or '
'"write_config" (or press CTRL+D to exit): '
).strip()
except EOFError:
print("")
break
Expand Down Expand Up @@ -337,5 +349,7 @@ def get_value_from_user(sc):

continue

print("No symbol/choice named '{}' in the configuration".format(cmd),
file=sys.stderr)
print(
"No symbol/choice named '{}' in the configuration".format(cmd),
file=sys.stderr,
)
11 changes: 7 additions & 4 deletions examples/merge_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,10 @@
user_value = sym.user_value

if user_value != sym.str_value:
print("warning: {} was assigned the value '{}' but got the "
"value '{}' -- check dependencies".format(
sym.name_and_loc, user_value, sym.str_value),
file=sys.stderr)
print(
"warning: {} was assigned the value '{}' but got the "
"value '{}' -- check dependencies".format(
sym.name_and_loc, user_value, sym.str_value
),
file=sys.stderr,
)
Loading