Skip to main content

A simple web-based configuration editor for Python applications.

Project description

pyConfigWebUI

Build Status License Latest Release Tag Latest PyPI Version

A simple web-based configuration editor for Python applications.

This package provides tools for editing configuration files in a user-friendly web interface.

Package on PyPI: configwebui-lucien · PyPI

Try it out

To get an intuitive understanding of how to use this tool, you can do the following:

  1. Clone this repository
git clone https://github.com/lucienshawls/py-config-web-ui
cd ./py-config-web-ui
  1. Install dependencies in a virtual environment or a conda environment (to avoid conflicts)
pip install -r ./requirements.txt
  1. Run demo!
python ./examples/demo.py
  1. Switch to your web browser

If your browser does not pop up, visit the link that shows in your terminal.

  1. Edit and save any config
  2. See if your config has been saved to ./examples/config
  3. Click Launch main program (a submenu from Save) and checkout the terminal

It should output some messages based on your config.

Use it in your own project

  1. Install

In the environment of your own project, run:

pip install configwebui-lucien
  1. Integrate

In your python file, import this package:

from configwebui import ConfigEditor, UserConfig, ResultStatus

or:

from configwebui import *

They have exactly the same effect.

  1. Optional preparations
  • Set up a function that varifies the config

When user clicks the Save button on the webpage, the config will first pass the extra validations before it can be saved to the memory. You can set up your own validation function.

Your function should take one positional argument, which is for the config itself (config).

Your function should return a ResultStatus object or a boolean value. If you choose the former, you can attach several error messages that the user can see on the webpage.

This function is related to a specific UserConfig that you set up later.

Example:

def always_pass(config: dict | list) -> ResultStatus:
    # Instantiate a ResultStatus object with no messages, and set its status to True.
    res = ResultStatus(True)
    if False:
        # Just to show what to do when validation fails
        res.set_status(False)
        res.add_message("message 1")
        res.add_message("message 2")

    return res
  • Set up a function that saves config

When user clicks the Save button on the webpage, and after the config passes extra validations, the config is saved to the memory immediately and your save function is then called in a separate thread.

You can choose not to set the save function; however, if you do so, all edited configurations will only remain in memory and cannot be read, and will disappear when the program is restarted.

Your function should take one positional argument, which is for the config itself (config).

You can freely choose the type (json, yaml, toml, etc.) and save method of the configuration file.

Parameter validation is not needed. It is guaranteed that the parameters satisfy your requirements.

Return values are not needed either, because for now, the package does not read the result.

This function is related to a specific UserConfig that you set up later.

Example:

import json
import os
def my_save(config: dict | list):
    # You don't need to perform parameter validation
    os.makedirs("./config", exist_ok=True)
    with open("config/myconfig.json", "w", encoding="utf-8") as f:
        json.dump(config, f, indent=4)
    print(config)
  • Set up a main entry point

When user clicks Launch main program button on the webpage, your save function is called in a separate thread.

Your function should take no positional arguments.

Return values are not needed.

This function is related to a specific ConfigEditor that you set up later.

ATTENTION: Your main entry should be treated as an independent program that independently obtains configurations from the location where the configuration file is saved, and executes the code. Therefore, when the main entry is called, configuration-related parameters will not be passed in.

Example:

import os
import json
def my_main_entry():
    print("======== This is main entry =======")
    if os.path.exists("config/myconfig.json"):
        with open("config/myconfig.json", "r", encoding="utf-8") as f:
            config = json.load(f)
        print(config)
  1. Fire it up

Instantiate a ConfigEditor object, and add one or more config schema to it:

import os
schema = {
    "title": "Example Schema",
    "type": "object",
    "properties": {
        "name": {"type": "string", "title": "Name"},
        "age": {"type": "integer", "title": "Age"},
        "is_student": {"type": "boolean"},
    },
}  # You need to create this
# Create a ConfigEditor object
config_editor = ConfigEditor(
    app_name="Trial",  # display name, is used in the webpage title
    main_entry=my_main_entry,  # optional, main entry point, make sure it can run in a thread.
)

# Create a UserConfig object
user_config = UserConfig(
    name="myconfig",  # identifier
    friendly_name="Main config",  # display name
    schema=schema,  # schema
    extra_validation_func=always_pass,  # optional, extra validation function
    save_func=my_save,  # optional, save function
)

# Load the config from file and set initial values (or not, as you wish)
def load_config(name: str) -> dict | list:
    file_path = f"config/{name}.json"
    if os.path.exists(file_path):
        with open(file_path, "r", encoding="utf-8") as f:
            config = json.load(f)
    else:
        config = None
    return config

config_from_file = load_config("myconfig")
if config_from_file is not None:
    user_config.set_config(
        config=config_from_file,
        skip_schema_validations=True,  # optional, skip schema validations this time only
        skip_extra_validations=True,  # optional, skip extra validations this time only
    )

# Add the UserConfig object to the ConfigEditor object
config_editor.add_user_config(user_config=user_config)
  1. Run it

Run the ConfigEditor!

Example:

# Change the port to 5000 if you do not have enough permissions.
config_editor.run(host="localhost", port=80)

Acknowledgements

I would like to express my gratitude to the following projects and individuals for different scenarios and reasons:

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

configwebui_lucien-0.2.1.tar.gz (1.6 MB view details)

Uploaded Source

Built Distribution

configwebui_lucien-0.2.1-py3-none-any.whl (1.6 MB view details)

Uploaded Python 3

File details

Details for the file configwebui_lucien-0.2.1.tar.gz.

File metadata

  • Download URL: configwebui_lucien-0.2.1.tar.gz
  • Upload date:
  • Size: 1.6 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.7

File hashes

Hashes for configwebui_lucien-0.2.1.tar.gz
Algorithm Hash digest
SHA256 23eba8204fea3865f5fe3d817ad2c62a6ad9b7f62d2e72aa9ece0d6534f97420
MD5 9aa5c3700b9242a7d2a2a9348edce3a8
BLAKE2b-256 4db7389eb2acf6eafb2c8905fe2aa171d0bb12d89af031653ee72dbbad35f7f4

See more details on using hashes here.

File details

Details for the file configwebui_lucien-0.2.1-py3-none-any.whl.

File metadata

File hashes

Hashes for configwebui_lucien-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 fe71687e0b8422252ccf677763aab374a351d2abcaa1e866a5e0ff0f60c82a74
MD5 9380c5650632d4df9d0cc2adc99634d8
BLAKE2b-256 b78f317aee8a7d168ff78cb541bb75e118f1a748dd53b603a5a54cd0c094aee8

See more details on using hashes here.

Supported by

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