kopia lustrzana https://github.com/Yakifo/amqtt
updating docs to pull descriptions from structured configs
rodzic
1ec555ca23
commit
1be3a7c848
|
@ -3,7 +3,7 @@ from dataclasses import dataclass, field, fields, replace, asdict
|
||||||
from enum import Enum, StrEnum
|
from enum import Enum, StrEnum
|
||||||
import logging
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import TYPE_CHECKING, Any
|
from typing import TYPE_CHECKING, Any, LiteralString, Literal
|
||||||
|
|
||||||
from amqtt.mqtt.constants import QOS_0
|
from amqtt.mqtt.constants import QOS_0
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ class ListenerType(StrEnum):
|
||||||
|
|
||||||
class Dictable:
|
class Dictable:
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
return getattr(self, key)
|
return self.get(key)
|
||||||
|
|
||||||
def get(self, name, default=None):
|
def get(self, name, default=None):
|
||||||
if hasattr(self, name):
|
if hasattr(self, name):
|
||||||
|
@ -43,34 +43,6 @@ class Dictable:
|
||||||
return default
|
return default
|
||||||
raise ValueError(f"'{name}' is not defined")
|
raise ValueError(f"'{name}' is not defined")
|
||||||
|
|
||||||
def copy(self):
|
|
||||||
return replace(self)
|
|
||||||
|
|
||||||
def update(self, other):
|
|
||||||
if not isinstance(other, self.__class__):
|
|
||||||
raise TypeError(f'must update with another {self.__class__.__name__}')
|
|
||||||
for f in fields(self):
|
|
||||||
if isinstance(getattr(self, f.name), Dictable):
|
|
||||||
setattr(self, f.name, getattr(self, f.name).update(getattr(other, f.name)))
|
|
||||||
if getattr(self, f.name) == f.default:
|
|
||||||
setattr(self, f.name, other[f.name])
|
|
||||||
|
|
||||||
# if not isinstance(other, self.__class__):
|
|
||||||
# raise TypeError(f'must update with another {self.__class__.__name__}')
|
|
||||||
#
|
|
||||||
# valids = { k:v for k,v in asdict(self).items() if v is not None }
|
|
||||||
# return replace(other, **valids)
|
|
||||||
|
|
||||||
def __ior__(self, other):
|
|
||||||
self.update(other)
|
|
||||||
return self
|
|
||||||
# if not isinstance(other, self.__class__):
|
|
||||||
# raise TypeError(f'must update with another {self.__class__.__name__}')
|
|
||||||
# for f in fields(self):
|
|
||||||
# if getattr(self, f.name) == f.default:
|
|
||||||
# setattr(self, f.name, other[f.name])
|
|
||||||
# return self
|
|
||||||
|
|
||||||
def __contains__(self, name):
|
def __contains__(self, name):
|
||||||
return getattr(self, name, None) is not None
|
return getattr(self, name, None) is not None
|
||||||
|
|
||||||
|
@ -80,10 +52,13 @@ class Dictable:
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class ListenerConfig(Dictable):
|
class ListenerConfig:
|
||||||
type: ListenerType = ListenerType.TCP
|
type: ListenerType = ListenerType.TCP
|
||||||
|
"""listener type: 'tcp' or 'ws'"""
|
||||||
bind: str | None = "0.0.0.0:1883"
|
bind: str | None = "0.0.0.0:1883"
|
||||||
|
"""address and port for the listener to bind to"""
|
||||||
max_connections: int = 0
|
max_connections: int = 0
|
||||||
|
""""""
|
||||||
ssl: bool = False
|
ssl: bool = False
|
||||||
cafile: str | Path | None = None
|
cafile: str | Path | None = None
|
||||||
capath: str | Path | None = None
|
capath: str | Path | None = None
|
||||||
|
@ -96,6 +71,15 @@ class ListenerConfig(Dictable):
|
||||||
if isinstance(getattr(self, fn), str):
|
if isinstance(getattr(self, fn), str):
|
||||||
setattr(self, fn, Path(getattr(self, fn)))
|
setattr(self, fn, Path(getattr(self, fn)))
|
||||||
|
|
||||||
|
def apply(self, other):
|
||||||
|
"""Apply the field from 'other', if 'self' field is default."""
|
||||||
|
if not isinstance(other, ListenerConfig):
|
||||||
|
msg = f'cannot apply {self.__class__.__name__} to {other.__class__.__name__}'
|
||||||
|
raise TypeError(msg)
|
||||||
|
for f in fields(self):
|
||||||
|
if getattr(self, f.name) == f.default:
|
||||||
|
setattr(self, f.name, other[f.name])
|
||||||
|
|
||||||
def default_listeners():
|
def default_listeners():
|
||||||
return {
|
return {
|
||||||
'default': ListenerConfig()
|
'default': ListenerConfig()
|
||||||
|
@ -112,12 +96,20 @@ def default_broker_plugins():
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class BrokerConfig(Dictable):
|
class BrokerConfig(Dictable):
|
||||||
listeners: dict[str, ListenerConfig] = field(default_factory=dict)
|
"""Structured configuration for a broker. Can be passed directly to `amqtt.broker.Broker` or created from a dictionary.
|
||||||
|
"""
|
||||||
|
listeners: dict[Literal['default'] | str, ListenerConfig] = field(default_factory=default_listeners)
|
||||||
|
"""Network of listeners used by the services."""
|
||||||
sys_interval: int | None = None
|
sys_interval: int | None = None
|
||||||
|
"""Deprecated field to configure the `BrokerSysPlugin`"""
|
||||||
timeout_disconnect_delay: int | None = 0
|
timeout_disconnect_delay: int | None = 0
|
||||||
plugins: dict | list | None = None
|
"""Client disconnect timeout without a keep-alive."""
|
||||||
auth: dict[str, Any] | None = None
|
auth: dict[str, Any] | None = None
|
||||||
|
"""Deprecated field used to config EntryPoint-loaded plugins."""
|
||||||
topic_check: dict[str, Any] | None = None
|
topic_check: dict[str, Any] | None = None
|
||||||
|
"""Deprecated field used to config EntryPoint-loaded plugins."""
|
||||||
|
plugins: dict | list | None = None
|
||||||
|
"""A list of strings representing the modules and class name of `BasePlugin`, `BaseAuthPlugin` and `BaseTopicPlugins`."""
|
||||||
|
|
||||||
def __post__init__(self) -> None:
|
def __post__init__(self) -> None:
|
||||||
if self.sys_interval is not None:
|
if self.sys_interval is not None:
|
||||||
|
@ -130,7 +122,9 @@ class BrokerConfig(Dictable):
|
||||||
|
|
||||||
default_listener = self.listeners['default']
|
default_listener = self.listeners['default']
|
||||||
for listener_name, listener in self.listeners.items():
|
for listener_name, listener in self.listeners.items():
|
||||||
listener.update(default_listener)
|
if listener_name == 'default':
|
||||||
|
continue
|
||||||
|
listener.apply(default_listener)
|
||||||
|
|
||||||
if isinstance(self.plugins, list):
|
if isinstance(self.plugins, list):
|
||||||
_plugins = {}
|
_plugins = {}
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
{% extends "base.html" %}
|
|
||||||
|
|
||||||
{% block outdated %}
|
|
||||||
You're not viewing the latest version.
|
|
||||||
<a href="{{ '../' ~ base_url }}">
|
|
||||||
<strong>Click here to go to latest.</strong>
|
|
||||||
</a>
|
|
||||||
{% endblock %}
|
|
|
@ -3,6 +3,22 @@
|
||||||
This configuration structure is valid as a python dictionary passed to the `amqtt.broker.Broker` class's `__init__` method or
|
This configuration structure is valid as a python dictionary passed to the `amqtt.broker.Broker` class's `__init__` method or
|
||||||
as a yaml formatted file passed to the `amqtt` script.
|
as a yaml formatted file passed to the `amqtt` script.
|
||||||
|
|
||||||
|
|
||||||
|
::: amqtt.contexts.BrokerConfig
|
||||||
|
options:
|
||||||
|
heading_level: 3
|
||||||
|
extra:
|
||||||
|
class_style: "simple"
|
||||||
|
|
||||||
|
::: amqtt.contexts.ListenerConfig
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### Manual docs
|
||||||
|
|
||||||
### `listeners` *(list[dict[str, Any]])*
|
### `listeners` *(list[dict[str, Any]])*
|
||||||
|
|
||||||
Defines the network listeners used by the service. Items defined in the `default` listener will be
|
Defines the network listeners used by the service. Items defined in the `default` listener will be
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
{% extends "_base/class.html.jinja" %}
|
||||||
|
|
||||||
|
{% block signature scoped %}
|
||||||
|
{% if config.extra.class_style != 'simple' %}
|
||||||
|
{{ super() }}
|
||||||
|
{% endif %}
|
||||||
|
{% endblock signature %}
|
||||||
|
|
||||||
|
{% block bases scoped %}
|
||||||
|
{% if config.extra.class_style != 'simple' %}
|
||||||
|
{{ super() }}
|
||||||
|
{% endif %}
|
||||||
|
{% endblock bases %}
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "_base/attribute.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
<p style="color:red">attribute.html.jinja</p>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "_base/backlinks.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
<p style="color:red">backlinks.html.jinja</p>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "_base/children.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
<p style="color:red">children.html.jinja</p>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "_base/class.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
<p style="color:red">class.html.jinja</p>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "_base/docstring.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
<p style="color:red">docstring.html.jinja</p>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "_base/docstring/admonition.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
<p style="color:red">docstring/admonition.html.jinja</p>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "_base/docstring/attributes.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
<p style="color:red">docstring/attributes.html.jinja</p>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "_base/docstring/classes.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
<p style="color:red">docstring/classes.html.jinja</p>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "_base/docstring/examples.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
<p style="color:red">docstring/examples.html.jinja</p>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "_base/docstring/functions.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
<p style="color:red">docstring/functions.html.jinja</p>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "_base/docstring/modules.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
<p style="color:red">docstring/modules.html.jinja</p>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "_base/docstring/other_parameters.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
<p style="color:red">docstring/other_parameters.html.jinja</p>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "_base/docstring/parameters.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
<p style="color:red">docstring/parameters.html.jinja</p>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "_base/docstring/raises.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
<p style="color:red">docstring/raises.html.jinja</p>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "_base/docstring/receives.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
<p style="color:red">docstring/receives.html.jinja</p>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "_base/docstring/returns.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
<p style="color:red">docstring/returns.html.jinja</p>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "_base/docstring/warns.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
<p style="color:red">docstring/warns.html.jinja</p>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "_base/docstring/yields.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
<p style="color:red">docstring/yields.html.jinja</p>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
{% extends "_base/expression.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
|
||||||
|
<< expression.html.jinja >>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "_base/function.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
<p style="color:red">function.html.jinja</p>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "_base/labels.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
<p style="color:red">labels.html.jinja</p>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "_base/language.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
<p style="color:red">language.html.jinja</p>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "_base/languages/en.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
<p style="color:red">languages/en.html.jinja</p>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "_base/languages/ja.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
<p style="color:red">languages/ja.html.jinja</p>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "_base/languages/zh.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
<p style="color:red">languages/zh.html.jinja</p>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "_base/module.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
<p style="color:red">module.html.jinja</p>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "_base/signature.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
<< signature.html.jinja >>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "_base/summary.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
<p style="color:red">summary.html.jinja</p>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "_base/summary/attributes.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
<p style="color:red">summary/attributes.html.jinja</p>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "_base/summary/classes.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
<p style="color:red">summary/classes.html.jinja</p>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "_base/summary/functions.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
<p style="color:red">summary/functions.html.jinja</p>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "_base/summary/modules.html.jinja" %}
|
||||||
|
|
||||||
|
{% block logs scoped %}
|
||||||
|
<p style="color:red">summary/modules.html.jinja</p>
|
||||||
|
{% endblock logs %}
|
||||||
|
|
||||||
|
|
|
@ -127,10 +127,12 @@ plugins:
|
||||||
- coverage
|
- coverage
|
||||||
- mkdocs-typer2
|
- mkdocs-typer2
|
||||||
- mkdocstrings:
|
- mkdocstrings:
|
||||||
|
custom_templates: 'docs/templates'
|
||||||
handlers:
|
handlers:
|
||||||
python:
|
python:
|
||||||
paths: [amqtt]
|
paths: [amqtt]
|
||||||
options:
|
options:
|
||||||
|
annotation_path: "full"
|
||||||
docstring_options:
|
docstring_options:
|
||||||
ignore_init_summary: true
|
ignore_init_summary: true
|
||||||
docstring_section_style: list
|
docstring_section_style: list
|
||||||
|
@ -148,6 +150,8 @@ plugins:
|
||||||
show_symbol_type_toc: true
|
show_symbol_type_toc: true
|
||||||
signature_crossrefs: true
|
signature_crossrefs: true
|
||||||
summary: true
|
summary: true
|
||||||
|
extensions:
|
||||||
|
|
||||||
- git-revision-date-localized:
|
- git-revision-date-localized:
|
||||||
enabled: !ENV [DEPLOY, false]
|
enabled: !ENV [DEPLOY, false]
|
||||||
enable_creation_date: true
|
enable_creation_date: true
|
||||||
|
|
|
@ -10,88 +10,6 @@ from amqtt.contexts import BrokerConfig, ListenerConfig, Dictable
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class NestedData(Dictable):
|
|
||||||
nested_one: int | None = None
|
|
||||||
nested_two: str | None = None
|
|
||||||
nested_three: str | None = "empty option"
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class MainData(Dictable):
|
|
||||||
main_one: str | None = None
|
|
||||||
main_two: str | None = 2
|
|
||||||
main_three: dict[str, NestedData] | None = field(default_factory=dict)
|
|
||||||
|
|
||||||
|
|
||||||
data_a = {
|
|
||||||
'main_one': 'value main one',
|
|
||||||
'main_three': {
|
|
||||||
'nested_key_one': {
|
|
||||||
'nested_one': 101,
|
|
||||||
'nested_two': 'value nested two'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data_b = {
|
|
||||||
'option_one': 'value ten'
|
|
||||||
}
|
|
||||||
|
|
||||||
data_c = {
|
|
||||||
'main_two': 'value main two',
|
|
||||||
'main_three': {
|
|
||||||
'nested_key_one': {
|
|
||||||
'nested_two': 'other nested two'
|
|
||||||
},
|
|
||||||
'nested_key_two': {
|
|
||||||
'nested_one': 202,
|
|
||||||
'nested_three': 'other nested three'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def test_mismatched_data():
|
|
||||||
|
|
||||||
with pytest.raises(UnexpectedDataError):
|
|
||||||
_ = from_dict(data_class=MainData, data=data_b, config=Config(cast=[StrEnum], strict=True))
|
|
||||||
|
|
||||||
def test_nested_data():
|
|
||||||
main_a = from_dict(data_class=MainData, data=data_a, config=Config(cast=[StrEnum], strict=True))
|
|
||||||
main_c = from_dict(data_class=MainData, data=data_c, config=Config(cast=[StrEnum], strict=True))
|
|
||||||
|
|
||||||
main_a.update(main_c)
|
|
||||||
|
|
||||||
assert isinstance(main_c, MainData)
|
|
||||||
assert isinstance(main_c, MainData)
|
|
||||||
assert isinstance(main_c.main_three, dict)
|
|
||||||
assert 'nested_key_one' in main_c.main_three
|
|
||||||
assert isinstance(main_c.main_three['nested_key_one'], NestedData)
|
|
||||||
assert 'nested_key_two' in main_c.main_three
|
|
||||||
|
|
||||||
assert main_c.main_three['nested_key_two'].nested_two == 'value nested two'
|
|
||||||
|
|
||||||
assert main_a.main_one == 'value main one'
|
|
||||||
assert main_a.main_two == 'value main two'
|
|
||||||
assert main_a.main_three['nested_key_one'].nested_two == 'other nested two'
|
|
||||||
assert main_a.main_three['nested_key_one'] == 'value twelve'
|
|
||||||
assert main_a.main_three['nested_key_one'] == 'value three'
|
|
||||||
|
|
||||||
|
|
||||||
data = {
|
|
||||||
"listeners": {
|
|
||||||
"default": {
|
|
||||||
"bind": "0.0.0.0:1883",
|
|
||||||
"max_connections": 50
|
|
||||||
},
|
|
||||||
"secure": {
|
|
||||||
"bind": "0.0.0.0:8883",
|
|
||||||
"cafile": "ca.key"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def _test_broker_config():
|
def _test_broker_config():
|
||||||
# Parse with dacite
|
# Parse with dacite
|
||||||
|
|
Ładowanie…
Reference in New Issue