Skip to main content

A simple feature managment tool library

Project description

pyconfix

A single‑file, curses‑powered, menuconfig‑style configuration editor for any project.


Why?

Do you need an interactive config menu like Linux menuconfig, but without C or a build step? pyconfix is forty kilobytes of pure Python you can drop into any repo—no external deps, no compilation. It also spits out JSON or Kconfig‑style header files, so it plugs straight into C/C++, CMake, Conan, Makefiles—anything that can consume a generated file.


Features

  • 🗂 Hierarchical optionsbool, int, string, multiple_choice, recursive groups.
  • 🔀 Boolean & arithmetic dependencies with logical operators &&, ||, ! (keyword forms and, or, xor), comparison/relational operators (==, !=, >, >=, <, <=), arithmetic expressions (+, -, *, /, %), and bitwise operators (&, |, ^, <<, >>).
  • 📦 Composable schemas"include": [ ... ] lets you split large configs.
  • 🔍 Instant search (/).
  • Abort keyCtrl+A exits search, input boxes etc.
  • 🎚 Live validation – options auto‑hide when dependencies fail.
  • 💾 Pluggable save hook – write JSON, YAML, C headers, env‑files – whatever.
  • 💻 100 % standard library (Windows users: pip install windows‑curses).

Installation

pip install pyconfix

Quick start

Create a tiny launcher script first:

# menu.py
import pyconfix

pyconfix.pyconfix(schem_file=["schem.json"]).run()

Then run it:

python menu.py

Press / to search, Enter to toggle, s to save, q to quit.


Headless / CI mode

Run the schema parser non‑interactively to dump a JSON config – handy for scripts and pipelines:

python - <<'PY'
import pyconfix, json
cfg = pyconfix.pyconfix(
    schem_file=["schem.json"],
    output_file="cfg.json",
    config_file="prev.json"
)
cfg.run(graphical=False)
PY

Python API

If you’d rather drive everything from code, import the class:

from pyconfix import pyconfix

cfg = pyconfix(
    schem_file=["main.json", "extras.json"],
    config_file="prev.json",      # load an existing config (optional)
    output_file="final.json",     # where to write when you press "s"
    expanded=True,                 # expand all groups initially
    show_disabled=True             # show options that currently fail deps
)

cfg.run()                # interactive TUI
print(cfg.get("HOST"))   # access a value programmatically

Constructor signature for reference:

pyconfix(
    schem_file: list[str],
    config_file: str | None = None,
    output_file: str = "output_config.json",
    save_func: Callable[[dict, list], None] | None = None,
    expanded: bool = False,
    show_disabled: bool = False,
)

Key bindings

Action Key
Navigate ↑ / ↓
Toggle / edit option Enter
Collapse / expand group c
Search /
Save s
Show option description Ctrl+D
Help h
Abort search / input Ctrl+A
Quit q

Schema format

{
  "name": "Main Config",
  "options": [
    { "name": "ENABLE_FEATURE_A", "type": "bool", "default": true },

    { "name": "LogLevel",
      "type": "multiple_choice",
      "default": "INFO",
      "choices": ["DEBUG", "INFO", "WARN", "ERROR"],
      "dependencies": "ENABLE_FEATURE_A" },

    { "name": "TIMEOUT",
      "type": "int",
      "default": 10,
      "dependencies": "ENABLE_FEATURE_A && LogLevel==DEBUG" },

    { "name": "Network", "type": "group", "options": [
        { "name": "HOST", "type": "string", "default": "localhost" }
    ]}
  ],
  "include": ["extra_schem.json"]
}

Supported option types

Type Notes
bool true / false
int any integer
string unicode string
multiple_choice one value from choices
group nests other options

Dependency syntax – cheatsheet

!ENABLE_FEATURE_A                     # logical NOT
ENABLE_FEATURE_A && HOST=="dev"       # logical AND + comparison
TIMEOUT>5 || HOST=="localhost"        # logical OR  + relational
COUNT+5 > MAX_VALUE                   # addition + relational
SIZE-1 >= MIN_SIZE                    # subtraction + comparison
VALUE*2 == LIMIT                      # multiplication + equality
RATIO/3 < 1                           # division + relational
SIZE%4==0                             # modulus check
POWER**2 <= LIMIT                     # exponentiation + relational
BITS & 0xFF == 0xAA                   # bitwise AND + equality
FLAGS | FLAG_VERBOSE                  # bitwise OR
MASK ^ 0b1010                         # bitwise XOR
VALUE<<2 > 1024                       # left shift + relational
VALUE>>1 == 0                         # right shift + equality

Advanced usage

import json, pyconfix

def save_as_header(cfg, _):
    with open("config.h", "w") as f:
        for k, v in cfg.items():
            f.write(f"#define {k} {v}\n")

pyconfix.pyconfix(
    schem_file=["schem.json", "extras.json"],
    output_file="settings.json",
    save_func=save_as_header
).run()

Conan integration example

After you have saved a JSON config with pyconfix (e.g. settings.json), a Conan recipe can read that file to enable/disable features and tweak package options at build time.

# conanfile.py
from conan import ConanFile
import os, json

# Load the JSON produced by pyconfix at *import* time so we can
# populate default_options immediately (Conan expects a plain dict).
_cfg = {}
try:
    with open(os.getenv("CFG", "settings.json")) as f:
        _cfg = json.load(f)
except FileNotFoundError:
    # Fall back to built‑ins if the file isn't around yet (first run).
    pass

class MyProject(ConanFile):
    name = "myproject"
    version = "1.0"

    # Declare the build‑time options your project cares about
    options = {
        "feature_a": [True, False],
        "log_level": ["DEBUG", "INFO", "WARN", "ERROR"],
    }
    # Pull the defaults straight from the JSON file
    default_options = {
        "feature_a": bool(_cfg.get("ENABLE_FEATURE_A", False)),
        "log_level": _cfg.get("LogLevel", "INFO"),
    }

Call it with:

python pyconfix.py              # produce settings.json
CFG=settings.json conan install .

Roadmap

  • Add unit tests + GitHub Actions CI
  • Cache dependency evaluation for massive configs

Contributions are welcome – fork, hack, send PRs! :rocket:


© 2025 Nemesis – MIT License

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyconfix-0.6.0.tar.gz (14.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyconfix-0.6.0-py3-none-any.whl (14.5 kB view details)

Uploaded Python 3

File details

Details for the file pyconfix-0.6.0.tar.gz.

File metadata

  • Download URL: pyconfix-0.6.0.tar.gz
  • Upload date:
  • Size: 14.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.2

File hashes

Hashes for pyconfix-0.6.0.tar.gz
Algorithm Hash digest
SHA256 2f2e4c538dfa125ca0d4cc2e83e8aac836997bab5e03817ba9ca8fc3476bbdb9
MD5 add6271a3a4afb95174363853a3ef79f
BLAKE2b-256 baf25ea86e046962e45f40a870ff4c246ce87d0da8821f9bf1c254523f9dea66

See more details on using hashes here.

File details

Details for the file pyconfix-0.6.0-py3-none-any.whl.

File metadata

  • Download URL: pyconfix-0.6.0-py3-none-any.whl
  • Upload date:
  • Size: 14.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.2

File hashes

Hashes for pyconfix-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 59ff95ee1e0f37dca0523ef96c994ca69f55832afd1f5b43e7d56ec9e8cd127e
MD5 d0c4ff8dabfa2a089c2f6ae417891242
BLAKE2b-256 87ac7b9db7529a946250f44d351cb39ed32f89f22d94e171bdf9d5c33cd4e178

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page