Skip to main content

Python File as Property File. Configuration in Python Itself.

Project description

ProperPy - Declarative Configuration Using Python Itself

Python Version License

👉中文

ProperPy is a Python-based declarative configuration parsing tool and structured data generation tool, integrating component-based development ideas with Python's native syntax, offering:

  • Definition file (schema.py) — like JSON Schema
    • 🧩 React/Compose style component-based configuration building
    • 🔒 Pydantic constraint support
  • Configuration file (.proper.py) — like JSON/TOML/YAML
    • 🐍 Pure Python syntax to implement DSL
    • ⚙️ Declarative configuration syntax
    • IDE type hints based on Python when writing
  • Parsing configuration — like GSON
    • 🛡️ Dynamic dependency resolution and type safety

Quick Start

Installation

pip install properpy

Basic Usage

Writing Definition File (config_schema.py)

The definition file refers to the file that defines the number of configuration items and the types of configuration items. It is usually used to verify the legality of configuration items and provide type hints when writing. ProperPy provides two decorators to help build definition files.

  1. component decorator. Wraps the function used to validate parameters into a component function that can support input of various dictionaries and subcomponents.
  2. config_wraper(RECEIVER) decorator factory. Same as above.

Functions wrapped by these two decorators are called components, which are a series of functions for parameter validation. Components will return a dictionary representing the component structure. For config_wraper, if RECEIVER is a dictionary, the result will be updated into RECEIVER; if it is a function, the result will be passed as a parameter to call this function.

According to the parameters passed to the component, the content of the result dictionary is as follows. If the positional parameters passed to the component are dictionaries and contain the tag key, they are treated as subcomponents; if they do not contain the tag key, they are merged into the result dictionary; if the parameters are keyword arguments, they are merged into the result dictionary.

  • 'tag': tag name (function name of the component)
  • 'children': subcomponents
  • ...attribute: keyword arguments parsed as dictionary attributes

The following example defines two components and a result receiving component.

from properpy import component, config_wrapper

@component
def html(title: str, class_: str = ""):
    pass

@component
def div(content: str, style: dict = None):
    pass

RESULT = {}
@config_wrapper(RESULT)
def define_config(html_component, title: str):
    pass

Writing Configuration File (config.proper.py)

The configuration file refers to the file that users need to configure based on the configuration item information provided by the definition file. Please use .proper.py as the suffix for ProperPy configuration files.

ProperPy provides the attrs function to help write configuration items.

The attrs function accepts any positional parameters (dictionary type) and keyword arguments, and merges them into a dictionary. It is mainly used to help convert keyword writing forms into dictionary writing forms.

The following example demonstrates how to call the result wrapper component and build the configuration file through component construction.

from config_schema import html, div, define_config
from properpy import attrs

other = "wrong"
define_config(
    html(
        div(
            attrs(style={"color": "red"}),
            "Dynamic content"
        ),
        class_="container"
    ),
    title="My App"
)

Parsing Configuration

ProperPy provides two ways to parse configurations and corresponding functions.

Parsing by Import

When using this method, you need to provide a receiving function or receiving dictionary in the definition file, and use config_wrapper to wrap the component. As in the RESULT in the above code.

Global variables in the configuration file need to be referenced through the imported module.

import_config: Dynamically import the module under a certain path and name it module_name

  • Parameters:
    • file_path:str: Path of the configuration file to import
    • module_name:str: Module naming, can be left blank (because the configuration file name contains illegal .proper, it will automatically be replaced with _)
  • Return value:ModuleType

Example code:

from properpy import import_config
from config_schema import RESULT

module = import_config("path/to/config.proper.py")
print(json.dumps(RESULT, indent=2))
# module.other is used to reference the global variable other

Output:

{
  "tag": "define_config",
  "children": [
    {
      "tag": "html",
      "children": [
        {
          "tag": "div",
          "children": [
            "Dynamic content"
          ],
          "style": {
            "color": "red"
          }
        }
      ],
      "class_": "container"
    }
  ],
  "title": "My App"
}
Parsing by Parser

This method performs static analysis on the entire file, and then dynamically executes the code in a sandbox after analysis, so a list of modules supported by the sandbox needs to be provided.

In this method, global variables will be added to the parsing result dictionary.

parse_config:

  • Parameters:
    • file_path_or_code:str|PathLike[str]|PathLike[bytes]: Configuration file path or configuration file code
    • supported_modules:list[str]: List of supported modules
    • supported_builtin_modules:list[ModuleTag]: List of supported Python built-in module types
      • ModuleTag.MONITOR: Built-in modules that require behavior monitoring
      • ModuleTag.NORMAL: Regular built-in modules
      • ModuleTag.RISK: Built-in modules containing risky behaviors
      • ModuleTag.BLOCKED: Built-in modules that should be blocked from parsing
    • module_paths:list[str]: Module search paths, default is empty
  • Return value:dict: Parsing result

Example code:

from properpy import parse_config, ModuleTag

result = parse_config("path/to/config.proper.py", ["config_schema"], [ModuleTag.NORMAL])
print(json.dumps(result, indent=2))

Output:

{
  "children": [
    {
      "tag": "define_config",
      "children": [
        {
          "tag": "html",
          "children": [
            {
              "tag": "div",
              "children": [
                "Dynamic content"
              ],
              "style": {
                "color": "red"
              }
            }
          ],
          "class_": "container"
        }
      ],
      "title": "My App"
    }
  ],
  "other": "wrong"
}

Contribution Guide

Package management tool uses uv

# Development environment setup
git clone https://github.com/yourusername/properpy.git
cd properpy
uv install

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

properpy-0.1.0.tar.gz (15.1 kB view details)

Uploaded Source

Built Distribution

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

properpy-0.1.0-py3-none-any.whl (12.7 kB view details)

Uploaded Python 3

File details

Details for the file properpy-0.1.0.tar.gz.

File metadata

  • Download URL: properpy-0.1.0.tar.gz
  • Upload date:
  • Size: 15.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.5.25

File hashes

Hashes for properpy-0.1.0.tar.gz
Algorithm Hash digest
SHA256 2980aef9383e9b2c012387114edfb7d97a173ee54bf5b4b578c2c602648dc4d7
MD5 8c4bbede7cf04763d692398edf7314b8
BLAKE2b-256 8b9bc1eff47db69d21661885f488523cf2075c3bb73412bc20feb323f4c54b27

See more details on using hashes here.

File details

Details for the file properpy-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: properpy-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 12.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.5.25

File hashes

Hashes for properpy-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1aa429a5d6db8adc31018ff42080a64030195043175cfc69dc70eb76831a70c2
MD5 671185c26bdd3e4ddb3c4f376fc9696c
BLAKE2b-256 2b8d9d1948e19dd85b14e990e096bb5d6979528c42b1598edf8e81acd7d88fdd

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