Skip to main content

Simple Conf

Basic Usage

import dataclasses
from typing import List
from uuid import uuid4

from simpleconf.config import BaseJsonConfig


@dataclasses.dataclass
class UserProfile(BaseJsonConfig):
    name: str = ""
    uid: int | str = -1
    email: str = ""
    password: str = ""
    is_admin: bool = False
    tags: List[str] = dataclasses.field(default_factory=list)


profile = UserProfile()
profile.name = "Tom"
profile.uid = uuid4().hex
profile.email = "tom@gmail.com"
profile.tags.extend(("Engineer", "Artist"))
# 序列化
serialized = profile.serialize(indent=2)
print(serialized)
# 保存到文件
profile.save("demo_profile.json")

# 反序列化
profile2 = UserProfile.deserialize(serialized)
print(profile2)

# 读取文件
profile3 = UserProfile.load("demo_profile.json")
print(profile3)

assert profile.uid == profile2.uid == profile3.uid

Multiple Formats

import dataclasses
from typing import List

from simpleconf.config import BaseJsonConfig, BaseTomlConfig, BaseYamlConfig


# 使用dataclass定义配置对象结构
# 支持将一个dataclass嵌入到其他dataclass中
# BaseAppConfig
#  - environment
#  - ServerConfig
#  - RuntimeConfig
#  - MySqlConfig
@dataclasses.dataclass
class ServerConfig(object):
    httpPort: int = 8080
    websocketPort: int = 8080
    domain: str = "localhost"
    password: str = ""
    bannedIps: List[str] = dataclasses.field(default_factory=list)
    bannedClientIds: List[str] = dataclasses.field(default_factory=list)
    bannedHostnames: List[str] = dataclasses.field(default_factory=list)


@dataclasses.dataclass
class RuntimeConfig(object):
    debug: bool = True
    enableLogging: bool = False


@dataclasses.dataclass
class MySqlConfig(object):
    host: str = 'localhost'
    user: str = ''
    password: str = ''
    database: str = ''


@dataclasses.dataclass
class BaseAppConfig(object):
    environment: str = "local"
    server: ServerConfig = ServerConfig()
    mysql: MySqlConfig = MySqlConfig()
    runtime: RuntimeConfig = RuntimeConfig()


# 提供继承
@dataclasses.dataclass
class AppJsonConfig(BaseAppConfig, BaseJsonConfig):
    pass


@dataclasses.dataclass
class AppTomlConfig(BaseAppConfig, BaseTomlConfig):
    pass


@dataclasses.dataclass
class AppYamlConfig(BaseAppConfig, BaseYamlConfig):
    pass


def test_json_config():
    json_conf = AppJsonConfig()
    json_conf.runtime.debug = True
    json_conf.mysql.user = "root"
    json_conf.mysql.password = "password"
    json_conf.mysql.database = "test_db"
    json_conf.server.bannedIps.append("999.999.999.999")
    json_conf.server.bannedClientIds.append("df3453rewr349543utff")
    serialized = json_conf.serialize(indent=2)
    print(serialized)
    json_conf2 = AppJsonConfig.deserialize(serialized)
    print(json_conf2)

    json_conf.save("test.json", indent=4)
    json_conf3 = AppJsonConfig.load("test.json")
    print(json_conf3)


def test_yaml_config():
    yaml_conf = AppYamlConfig()
    yaml_conf.runtime.debug = True
    yaml_conf.mysql.user = "root"
    yaml_conf.mysql.password = "password"
    yaml_conf.mysql.database = "test_db"
    yaml_conf.server.bannedIps.append("999.999.999.999")
    yaml_conf.server.bannedClientIds.append("df3453rewr349543utff")
    print(yaml_conf.serialize())

    yaml_conf2 = AppYamlConfig.deserialize(yaml_conf.serialize())
    print(yaml_conf2)

    yaml_conf2.save("test.yaml", indent=4)
    yaml_conf3 = AppYamlConfig.load("test.yaml")
    print(yaml_conf3)


def test_toml_config():
    toml_conf = AppTomlConfig()
    toml_conf.runtime.debug = True
    toml_conf.mysql.user = "root"
    toml_conf.mysql.password = "password"
    toml_conf.mysql.database = "test_db"
    toml_conf.server.bannedIps.append("999.999.999.999")
    toml_conf.server.bannedClientIds.append("df3453rewr349543utff")
    print(toml_conf.serialize())

    toml_conf2 = AppTomlConfig.deserialize(toml_conf.serialize())
    print(toml_conf2)

    toml_conf2.save("test.toml")
    toml_conf3 = AppTomlConfig.load("test.toml")
    print(toml_conf3)


if __name__ == '__main__':
    test_json_config()
    test_toml_config()
    test_yaml_config()

Field Validation

import dataclasses
from typing import List

import marshmallow.validate
from marshmallow import ValidationError

from simpleconf.config import BaseJsonConfig


@dataclasses.dataclass
class ProjectConfig(BaseJsonConfig):
    name: str
    description: str = "<description>"
    author: str = "<author>"
    author_email: str = "<email>"
    license: str = "MIT"
    version: str = "0.1"
    install_requires: List[str] = dataclasses.field(default_factory=list)


try:
    # 以下代码将引发异常,因为缺少必要字段"name"
    conf = ProjectConfig.deserialize("{}")
except ValidationError as e:
    print(e)

try:
    # 以下代码将引发异常,因为version字段不是字符串
    # 在上面的ProjectConfig类中,version的类型提示为str,若要其同时支持字符串和数字,可以使用 str|int作为其类型提示
    conf2 = ProjectConfig.deserialize(
        """{
        "name": "demo",
        "version": 1
        }"""
    )
except ValidationError as e:
    print(e)

try:
    # 以下代码将引发异常,因为install_requires被定义为List[str]类型,但下面的install_requires中的第一个元素为int类型
    conf3 = ProjectConfig.deserialize(
        """{
        "name": "demo",
        "version": "1.0",
        "install_requires": [1, "toml"]
        }"""
    )
except ValidationError as e:
    print(e)


# 除了类型注释可以为验证器提供足够的信息外,还可以利用dataclass字段的metadata信息为字段提供更加精细的验证器
# 做法是在metadata中添加一个validate属性,该属性的值为marshmallow.validate.Validator类的实例
# 例如在下面的User类中,age字段的metadata中添加了validate属性,其值为marshmallow自带的一个Validator——Range
# 作用是限制age字段的值必须在18~60之间
@dataclasses.dataclass
class User(BaseJsonConfig):
    name: str
    age: int = dataclasses.field(metadata={"validate": marshmallow.validate.Range(min=18, max=60)}, default=18)


try:
    # user1 ok
    user1 = User.deserialize("""{"name": "tom", "age": 18}""")
    # user2 会抛出异常,因为age的值超出了18~60的范围
    user2 = User.deserialize("""{"name": "tom", "age": 100}""")
except ValidationError as e:
    print(e)

Metadata

Release files for simple-dataclass-configuration 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for simple-dataclass-configuration 0.1.2
File Size Uploaded
simple_dataclass_configuration-0.1.2.tar.gz 5.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for simple-dataclass-configuration 0.1.2
File Interpreter ABI Platform
simple_dataclass_configuration-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 11.6 kB

Release files / simple_dataclass_configuration-0.1.2.tar.gz

Download URL simple_dataclass_configuration-0.1.2.tar.gz
Size 5.6 kB
Tags Source
SHA-256 checksum
How to use checksums
fda7d5fae57c05c7436c1d1b9bc495056f5d3b3d8b3501889a434b5de9118ec6
BLAKE2b-256 checksum
How to use checksums
32b6c88e93469f20feb49b245aed0a7ccecdc217362ae6325fe6756c00682702
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.7.1 CPython/3.10.8 Windows/10

Release files / simple_dataclass_configuration-0.1.2-py3-none-any.whl

Download URL simple_dataclass_configuration-0.1.2-py3-none-any.whl
Size 6.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9ee7c5ede402179e03c2cc37495a86a0dd76cb4569b1263de98c6db737d916f0
BLAKE2b-256 checksum
How to use checksums
03cb9da808f8ed64314073f215b5e8a1de798aa496e4c2db106dec44f9009ec3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.7.1 CPython/3.10.8 Windows/10

Release history Release notifications | RSS feed

This release

0.1.2 This release

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page