from pyscript import display from pyweb import pydom #from pyscript.web import page from pyscript import window, document, HTML from pyodide.ffi import create_proxy from tiramisu import * from tiramisu.setting import ALLOWED_LEADER_PROPERTIES # ROUGAIL from typing import Any try: from tiramisu5 import DynOptionDescription, calc_value except ModuleNotFoundError: from tiramisu import DynOptionDescription, calc_value from importlib.machinery import SourceFileLoader as _SourceFileLoader from importlib.util import ( spec_from_loader as _spec_from_loader, module_from_spec as _module_from_spec, ) from jinja2 import StrictUndefined, DictLoader from jinja2.sandbox import SandboxedEnvironment from tiramisu import function_waiting_for_error from tiramisu.error import ValueWarning, ConfigError, PropertiesOptionError from unicodedata import normalize, combining def normalize_family(family_name: str) -> str: """replace space, accent, uppercase, ... by valid character""" if not family_name: return family_name = family_name.lower() family_name = family_name.replace("-", "_").replace(" ", "_").replace(".", "_") nfkd_form = normalize("NFKD", family_name) family_name = "".join([c for c in nfkd_form if not combining(c)]) return family_name.lower() def display_xmlfiles(xmlfiles: list) -> str: """The function format xmlfiles informations to generate errors""" if len(xmlfiles) == 1: return '"' + xmlfiles[0] + '"' return '"' + '", "'.join(xmlfiles[:-1]) + '"' + " and " + '"' + xmlfiles[-1] + '"' def convert_boolean(value: str) -> bool: """Boolean coercion. The Rougail XML may contain srings like `True` or `False`""" if isinstance(value, bool): return value value = value.lower() if value == "true": return True elif value == "false": return False elif value in ["", None]: return None raise Exception(f'unknown boolean value "{value}"') CONVERT_OPTION = { "string": dict(opttype="StrOption", example="example"), "number": dict(opttype="IntOption", func=int, example=42), "float": dict(opttype="FloatOption", func=float, example=1.42), "boolean": dict(opttype="BoolOption", func=convert_boolean), "secret": dict(opttype="PasswordOption", example="secrets"), "mail": dict(opttype="EmailOption", example="user@example.net"), "unix_filename": dict(opttype="FilenameOption", example="/tmp/myfile.txt"), "date": dict(opttype="DateOption", example="2000-01-01"), "unix_user": dict(opttype="UsernameOption", example="username"), "ip": dict( opttype="IPOption", initkwargs={"allow_reserved": True}, example="1.1.1.1" ), "cidr": dict(opttype="IPOption", initkwargs={"cidr": True}, example="1.1.1.0/24"), "netmask": dict(opttype="NetmaskOption", example="255.255.255.0"), "network": dict(opttype="NetworkOption", example="1.1.1.0"), "network_cidr": dict( opttype="NetworkOption", initkwargs={"cidr": True}, example="1.1.1.0/24" ), "broadcast": dict(opttype="BroadcastOption", example="1.1.1.255"), "netbios": dict( opttype="DomainnameOption", initkwargs={"type": "netbios", "warnings_only": True}, example="example", ), "domainname": dict( opttype="DomainnameOption", initkwargs={"type": "domainname", "allow_ip": False}, example="example.net", ), "hostname": dict( opttype="DomainnameOption", initkwargs={"type": "hostname", "allow_ip": False}, example="example", ), "web_address": dict( opttype="URLOption", initkwargs={"allow_ip": False, "allow_without_dot": True}, example="https://example.net", ), "port": dict( opttype="PortOption", initkwargs={"allow_private": True}, example="111" ), "mac": dict(opttype="MACOption", example="00:00:00:00:00"), "unix_permissions": dict( opttype="PermissionsOption", initkwargs={"warnings_only": True}, func=int, example="644", ), "choice": dict(opttype="ChoiceOption", example="a_choice"), "regexp": dict(opttype="RegexpOption"), # "symlink": dict(opttype="SymLinkOption"), } global func dict_env = {} ENV = SandboxedEnvironment(loader=DictLoader(dict_env), undefined=StrictUndefined) func = ENV.filters ENV.compile_templates("jinja_caches", zip=None) class JinjaError: __slot__ = ("_err",) def __init__(self, err): self._err = err def __str__(self): raise self._err from self._err def __repr__(self): raise self._err from self._err def __eq__(self, *args, **kwargs): raise self._err from self._err def __ge__(self, *args, **kwargs): raise self._err from self._err def __gt__(self, *args, **kwargs): raise self._err from self._err def __le__(self, *args, **kwargs): raise self._err from self._err def __lt__(self, *args, **kwargs): raise self._err from self._err def __ne__(self, *args, **kwargs): raise self._err from self._err def test_propertyerror(value: Any) -> bool: return isinstance(value, JinjaError) ENV.tests["propertyerror"] = test_propertyerror def load_functions(path): global _SourceFileLoader, _spec_from_loader, _module_from_spec, func loader = _SourceFileLoader("func", path) spec = _spec_from_loader(loader.name, loader) func_ = _module_from_spec(spec) loader.exec_module(func_) for function in dir(func_): if function.startswith("_"): continue func[function] = getattr(func_, function) def rougail_calc_value(*args, __default_value=None, **kwargs): values = calc_value(*args, **kwargs) if __default_value is not None and values in [None, []]: return __default_value return values @function_waiting_for_error def jinja_to_function( __internal_variable, __internal_attribute, __internal_jinja, __internal_type, __internal_multi, __internal_files, __default_value=None, **kwargs, ): global ENV, CONVERT_OPTION kw = {} for key, value in kwargs.items(): if isinstance(value, PropertiesOptionError): value = JinjaError(value) if "." in key: c_kw = kw path, var = key.rsplit(".", 1) for subkey in path.split("."): c_kw = c_kw.setdefault(subkey, {}) c_kw[var] = value else: if key in kw: raise ConfigError( f'internal error, multi key for "{key}" in jinja_to_function' ) kw[key] = value try: values = ENV.get_template(__internal_jinja).render(kw, **func).strip() except Exception as err: raise ConfigError( f'cannot calculating "{__internal_attribute}" attribute for variable "{__internal_variable}" in {display_xmlfiles(__internal_files)}: {err}' ) from err convert = CONVERT_OPTION[__internal_type].get("func", str) if __internal_multi: values = [convert(val) for val in values.split("\n") if val != ""] if not values and __default_value is not None: return __default_value return values try: values = convert(values) except Exception as err: raise ConfigError( f'cannot converting "{__internal_attribute}" attribute for variable "{__internal_variable}" in {display_xmlfiles(__internal_files)}: {err}' ) from err values = values if values != "" and values != "None" else None if values is None and __default_value is not None: return __default_value return values def variable_to_property(prop, value, when, inverse): if isinstance(value, PropertiesOptionError): raise value from value if inverse: is_match = value != when else: is_match = value == when return prop if is_match else None @function_waiting_for_error def jinja_to_property(prop, when, inverse, **kwargs): value = func["jinja_to_function"](**kwargs) return func["variable_to_property"](prop, value is not None, when, inverse) @function_waiting_for_error def jinja_to_property_help(prop, **kwargs): value = func["jinja_to_function"](**kwargs) return (prop, f'"{prop}" ({value})') @function_waiting_for_error def valid_with_jinja(warnings_only=False, **kwargs): global ValueWarning value = func["jinja_to_function"](**kwargs) if value: if warnings_only: raise ValueWarning(value) else: raise ValueError(value) func["calc_value"] = rougail_calc_value func["jinja_to_function"] = jinja_to_function func["jinja_to_property"] = jinja_to_property func["jinja_to_property_help"] = jinja_to_property_help func["variable_to_property"] = variable_to_property func["valid_with_jinja"] = valid_with_jinja class ConvertDynOptionDescription(DynOptionDescription): """Identifier could be an integer, we should convert it in str Identifier could also contain invalid character, so we should "normalize" it """ def convert_identifier_to_path(self, identifier): if identifier is None: return identifier if not isinstance(identifier, str): identifier = str(identifier) return normalize_family(identifier) def impl_getname( self, identifier=None, ) -> str: """get name""" name = super().impl_getname(None) if identifier is None: return name path_identifier = self.convert_identifier_to_path(identifier) if "{{ identifier }}" in name: return name.replace("{{ identifier }}", path_identifier) return name + path_identifier def impl_get_display_name( self, subconfig, with_quote: bool = False, ) -> str: display = super().impl_get_display_name(subconfig, with_quote=with_quote) if "{{ identifier }}" in display: return display.replace( "{{ identifier }}", self.convert_identifier_to_path(self.get_identifiers(subconfig)[-1]), ) return display ################################################################ from re import compile as re_compile try: groups.namespace except: groups.addgroup('namespace') ALLOWED_LEADER_PROPERTIES.add("basic") ALLOWED_LEADER_PROPERTIES.add("standard") ALLOWED_LEADER_PROPERTIES.add("advanced") class Regexp_option_24(RegexpOption): __slots__ = tuple() _type = 'value' Regexp_option_24._regexp = re_compile(r"^#(?:[0-9a-f]{3}){1,2}$") dict_env['frozen_firefox.manual.{{ identifier }}_proxy.address'] = "{% if my_identifier == 'HTTPS' and _.use_for_https %}\nHTTPS is same has HTTP\n{% endif %}\n" dict_env['frozen_firefox.manual.{{ identifier }}_proxy.port'] = "{% if my_identifier == 'HTTPS' and _.use_for_https %}\nHTTPS is same has HTTP\n{% endif %}\n" dict_env['frozen_firefox.manual.{{ identifier }}_proxy.version'] = "{% if my_identifier == 'HTTPS' and _.use_for_https %}\nHTTPS is same has HTTP\n{% endif %}\n" dict_env['hidden_firefox.manual.{{ identifier }}_proxy'] = "{% if my_identifier == 'HTTPS' and _.use_for_https %}\nHTTPS is same has HTTP\n{% endif %}\n" dict_env['disabled_firefox.proxy_dns_socks5'] = "{% if _.manual.socks_proxy.version is propertyerror %}\nthe proxy mode is not manual\n{% elif _.manual.socks_proxy.version == 'v4' %}\nsocks version is v4\n{% endif %}\n" dict_env['validators_firefox.dns_over_https.custom_dns_url'] = "{% if dns_over_https.custom_dns_url.startswith('http://') %}\nonly https is allowed\n{% endif %}\n" dict_env['disabled_firefox.dns_over_https.custom_dns_url'] = "{% if _.provider is propertyerror or _.provider != 'Custom' %}\nprovider is not custom\n{% endif %}\n" dict_env['default_foxyproxy.proxies.color'] = "#\n{%- for i in range(6) -%}\n{{- '0123456789abcdef' | random -}}\n{%- endfor -%}\n" dict_env['default_foxyproxy.proxies.address'] = "{% if firefox.manual.http_proxy.address is not propertyerror %}\n{{ firefox.manual.http_proxy.address }}\n{% endif %}\n" dict_env['disabled_foxyproxy.proxies.address'] = "{% if _.type not in ['HTTP', 'HTTPS/SSL', 'SOCKS4', 'SOCKS5'] %}\ndisabled\n{% endif %}\n" dict_env['default_foxyproxy.proxies.port'] = "{% if firefox.manual.http_proxy.port is not propertyerror %}\n{{ firefox.manual.http_proxy.port }}\n{% endif %}\n" dict_env['disabled_foxyproxy.proxies.port'] = "{% if _.type not in ['HTTP', 'HTTPS/SSL', 'SOCKS4', 'SOCKS5'] %}\ndisabled\n{% endif %}\n" dict_env['disabled_foxyproxy.proxies.username'] = "{% if _.type not in ['HTTP', 'HTTPS/SSL', 'SOCKS4', 'SOCKS5'] %}\ndisabled\n{% endif %}\n" dict_env['hidden_foxyproxy.proxies.password'] = "{% if not _.username %}\nno username defined\n{% endif %}\n" dict_env['disabled_foxyproxy.proxies.password'] = "{% if _.type not in ['HTTP', 'HTTPS/SSL', 'SOCKS4', 'SOCKS5'] %}\ndisabled\n{% endif %}\n" dict_env['frozen_foxyproxy.proxies.password'] = "{% if not _.username %}\nno username defined\n{% endif %}\n" dict_env['default_foxyproxy.proxies.url'] = "{% if firefox.auto is not propertyerror %}\n{{ firefox.auto }}\n{% endif %}\n" dict_env['disabled_foxyproxy.proxies.url'] = "{% if _.type not in ['PAC URL', 'WPAD'] %}\nproxy does not need url\n{% endif %}\n" option_2 = ChoiceOption(name="proxy_mode", doc="Configure Proxy Access to the Internet", values=("No proxy", "Auto-detect proxy settings for this network", "Use system proxy settings", "Manual proxy configuration", "Automatic proxy configuration URL"), default="No proxy", properties=frozenset({"mandatory", "standard"}), informations={'type': 'choice', 'dictionaries': ['firefox/00-proxy.yml']}) option_5 = DomainnameOption(name="address", doc="HTTP address", type="domainname", allow_ip=True, properties=frozenset({"basic", "mandatory"}), informations={'type': 'domainname', 'dictionaries': ['firefox/10-manual.yml']}) option_6 = PortOption(name="port", doc="HTTP Port", default="8080", allow_private=True, properties=frozenset({"mandatory", "standard"}), informations={'type': 'port', 'dictionaries': ['firefox/10-manual.yml']}) optiondescription_4 = OptionDescription(name="http_proxy", doc="HTTP Proxy", children=[option_5, option_6], properties=frozenset({"basic"}), informations={'dictionaries': ['firefox/10-manual.yml']}) option_7 = BoolOption(name="use_for_https", doc="Also use this proxy for HTTPS", default=True, properties=frozenset({"mandatory", "standard"}), informations={'type': 'boolean', 'dictionaries': ['firefox/20-manual.yml']}) option_9 = DomainnameOption(name="address", doc="{{ identifier }} address", default=Calculation(func['calc_value'], Params((ParamOption(option_5)))), type="domainname", allow_ip=True, properties=frozenset({"force_default_on_freeze", "mandatory", "standard", Calculation(func['jinja_to_property'], Params((ParamValue("frozen")), kwargs={'__internal_jinja': ParamValue("frozen_firefox.manual.{{ identifier }}_proxy.address"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(False), '__internal_files': ParamValue(['firefox/20-manual.yml']), '__internal_attribute': ParamValue("frozen"), '__internal_variable': ParamValue("firefox.manual.{{ identifier }}_proxy.address"), 'my_identifier': ParamIdentifier(), 'when': ParamValue(True), 'inverse': ParamValue(False), '_.use_for_https': ParamOption(option_7, notraisepropertyerror=True)}), help_function=func['jinja_to_property_help'])}), informations={'type': 'domainname', 'default_calculation_type': 'variable', 'default_calculation': 'firefox.manual.http_proxy.address', 'dictionaries': ['firefox/20-manual.yml']}) option_10 = PortOption(name="port", doc="{{ identifier }} port", default=Calculation(func['calc_value'], Params((ParamOption(option_6)))), allow_private=True, properties=frozenset({"force_default_on_freeze", "mandatory", "standard", Calculation(func['jinja_to_property'], Params((ParamValue("frozen")), kwargs={'__internal_jinja': ParamValue("frozen_firefox.manual.{{ identifier }}_proxy.port"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(False), '__internal_files': ParamValue(['firefox/20-manual.yml']), '__internal_attribute': ParamValue("frozen"), '__internal_variable': ParamValue("firefox.manual.{{ identifier }}_proxy.port"), 'my_identifier': ParamIdentifier(), 'when': ParamValue(True), 'inverse': ParamValue(False), '_.use_for_https': ParamOption(option_7, notraisepropertyerror=True)}), help_function=func['jinja_to_property_help'])}), informations={'type': 'port', 'default_calculation_type': 'variable', 'default_calculation': 'firefox.manual.http_proxy.port', 'dictionaries': ['firefox/20-manual.yml']}) option_11 = ChoiceOption(name="version", doc="SOCKS host version used by proxy", values=("v4", "v5"), default="v5", properties=frozenset({"force_default_on_freeze", "mandatory", "standard", Calculation(func['variable_to_property'], Params((ParamValue("disabled"), ParamIdentifier()), kwargs={'when': ParamValue("HTTPS"), 'inverse': ParamValue(False)}), help_function=func['variable_to_property']), Calculation(func['jinja_to_property'], Params((ParamValue("frozen")), kwargs={'__internal_jinja': ParamValue("frozen_firefox.manual.{{ identifier }}_proxy.version"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(False), '__internal_files': ParamValue(['firefox/20-manual.yml']), '__internal_attribute': ParamValue("frozen"), '__internal_variable': ParamValue("firefox.manual.{{ identifier }}_proxy.version"), 'my_identifier': ParamIdentifier(), 'when': ParamValue(True), 'inverse': ParamValue(False), '_.use_for_https': ParamOption(option_7, notraisepropertyerror=True)}), help_function=func['jinja_to_property_help'])}), informations={'type': 'choice', 'dictionaries': ['firefox/20-manual.yml'], 'disabled_calculation_type': 'identifier', 'disabled_calculation': 'when the identifier is "HTTPS"'}) optiondescription_8 = ConvertDynOptionDescription(name="{{ identifier }}_proxy", doc="{{ identifier }} Proxy", identifiers=["HTTPS", "SOCKS"], children=[option_9, option_10, option_11], properties=frozenset({"standard", Calculation(func['jinja_to_property'], Params((ParamValue("hidden")), kwargs={'__internal_jinja': ParamValue("hidden_firefox.manual.{{ identifier }}_proxy"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(False), '__internal_files': ParamValue(['firefox/20-manual.yml']), '__internal_attribute': ParamValue("hidden"), '__internal_variable': ParamValue("firefox.manual.{{ identifier }}_proxy"), 'my_identifier': ParamIdentifier(), 'when': ParamValue(True), 'inverse': ParamValue(False), '_.use_for_https': ParamOption(option_7, notraisepropertyerror=True)}), help_function=func['jinja_to_property_help'])}), informations={'dictionaries': ['firefox/20-manual.yml'], 'hidden_calculation_type': 'jinja', 'hidden_calculation': 'in HTTPS case if "manual.use_for_https" is set to True\n'}) optiondescription_3 = OptionDescription(name="manual", doc="Manual proxy configuration", children=[optiondescription_4, option_7, optiondescription_8], properties=frozenset({"basic", Calculation(func['variable_to_property'], Params((ParamValue("disabled"), ParamOption(option_2)), kwargs={'when': ParamValue("Manual proxy configuration"), 'inverse': ParamValue(True)}), help_function=func['variable_to_property'])}), informations={'dictionaries': ['firefox/10-manual.yml', 'firefox/20-manual.yml'], 'disabled_calculation_type': 'variable', 'disabled_calculation': 'when the variable "firefox.proxy_mode" hasn\'t the value "Manual proxy configuration"'}) option_12 = URLOption(name="auto", doc="Automatic proxy configuration URL", allow_ip=False, allow_without_dot=True, properties=frozenset({"basic", "mandatory", Calculation(func['variable_to_property'], Params((ParamValue("disabled"), ParamOption(option_2)), kwargs={'when': ParamValue("Automatic proxy configuration URL"), 'inverse': ParamValue(True)}), help_function=func['variable_to_property'])}), informations={'type': 'web_address', 'dictionaries': ['firefox/30-auto.yml'], 'disabled_calculation_type': 'variable', 'disabled_calculation': 'when the variable "firefox.proxy_mode" hasn\'t the value "Automatic proxy configuration URL"'}) option_13 = DomainnameOption(name="no_proxy", doc="Address for which proxy will be desactivated", multi=True, type="domainname", allow_ip=True, allow_cidr_network=True, allow_without_dot=True, allow_startswith_dot=True, properties=frozenset({"standard", Calculation(func['variable_to_property'], Params((ParamValue("disabled"), ParamOption(option_2)), kwargs={'when': ParamValue("No proxy"), 'inverse': ParamValue(False)}), help_function=func['variable_to_property'])}), informations={'type': 'domainname', 'examples': ('.mozilla.org', '.net.nz', '192.168.1.0/24'), 'help': 'Connections to localhost, 127.0.0.1/8 and ::1 are never proxied', 'dictionaries': ['firefox/40-no_proxy.yml'], 'disabled_calculation_type': 'variable', 'disabled_calculation': 'when the variable "firefox.proxy_mode" has the value "No proxy"'}) option_14 = BoolOption(name="prompt_authentication", doc="Prompt for authentication if password is saved", default=True, properties=frozenset({"mandatory", "standard", Calculation(func['variable_to_property'], Params((ParamValue("disabled"), ParamOption(option_2)), kwargs={'when': ParamValue("No proxy"), 'inverse': ParamValue(False)}), help_function=func['variable_to_property'])}), informations={'type': 'boolean', 'dictionaries': ['firefox/50-prompt_authentication.yml'], 'disabled_calculation_type': 'variable', 'disabled_calculation': 'when the variable "firefox.proxy_mode" has the value "No proxy"'}) option_15 = BoolOption(name="proxy_dns_socks5", doc="Use proxy DNS when using SOCKS v5", default=False, properties=frozenset({"advanced", "mandatory", Calculation(func['jinja_to_property'], Params((ParamValue("disabled")), kwargs={'__internal_jinja': ParamValue("disabled_firefox.proxy_dns_socks5"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(False), '__internal_files': ParamValue(['firefox/55-proxy_dns_socks5.yml']), '__internal_attribute': ParamValue("disabled"), '__internal_variable': ParamValue("firefox.proxy_dns_socks5"), 'when': ParamValue(True), 'inverse': ParamValue(False), '_.manual.socks_proxy.version': ParamDynOption(option_11, ["socks"], notraisepropertyerror=True)}), help_function=func['jinja_to_property_help'])}), informations={'type': 'boolean', 'dictionaries': ['firefox/55-proxy_dns_socks5.yml'], 'disabled_calculation_type': 'jinja', 'disabled_calculation': 'if "firefox.proxy_mode" is not "Manual proxy configuration"\nor "firefox.manual.socks_proxy.version" is "v4"\n'}) option_17 = BoolOption(name="enable_dns_over_https", doc="Enable DNS over HTTPS", default=False, properties=frozenset({"mandatory", "standard"}), informations={'type': 'boolean', 'dictionaries': ['firefox/60-dns_over_https.yml']}) option_18 = ChoiceOption(name="provider", doc="Use Provider", values=("Cloudflare", "NextDNS", "Custom"), default="Cloudflare", properties=frozenset({"mandatory", "standard", Calculation(func['variable_to_property'], Params((ParamValue("disabled"), ParamOption(option_17)), kwargs={'when': ParamValue(False), 'inverse': ParamValue(False)}), help_function=func['variable_to_property'])}), informations={'type': 'choice', 'dictionaries': ['firefox/60-dns_over_https.yml'], 'disabled_calculation_type': 'variable', 'disabled_calculation': 'when the variable "firefox.dns_over_https.enable_dns_over_https" has the value "False"'}) option_19 = URLOption(name="custom_dns_url", doc="Custom DNS URL", validators=[Calculation(func['valid_with_jinja'], Params((), kwargs={'__internal_jinja': ParamValue("validators_firefox.dns_over_https.custom_dns_url"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(False), '__internal_files': ParamValue(['firefox/60-dns_over_https.yml']), '__internal_attribute': ParamValue("validators"), '__internal_variable': ParamValue("firefox.dns_over_https.custom_dns_url")}))], allow_ip=False, allow_without_dot=True, properties=frozenset({"basic", "mandatory", Calculation(func['jinja_to_property'], Params((ParamValue("disabled")), kwargs={'__internal_jinja': ParamValue("disabled_firefox.dns_over_https.custom_dns_url"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(False), '__internal_files': ParamValue(['firefox/60-dns_over_https.yml']), '__internal_attribute': ParamValue("disabled"), '__internal_variable': ParamValue("firefox.dns_over_https.custom_dns_url"), 'when': ParamValue(True), 'inverse': ParamValue(False), '_.provider': ParamOption(option_18, notraisepropertyerror=True)}), help_function=func['jinja_to_property_help'])}), informations={'type': 'web_address', 'validators_calculation_type_0': 'jinja', 'validators_calculation_0': "must starts with 'https://' only", 'dictionaries': ['firefox/60-dns_over_https.yml'], 'disabled_calculation_type': 'jinja', 'disabled_calculation': 'if "dns_over_https.provider" is not "Custom"'}) optiondescription_16 = OptionDescription(name="dns_over_https", doc="DNS over HTTPS", children=[option_17, option_18, option_19], properties=frozenset({"basic"}), informations={'dictionaries': ['firefox/60-dns_over_https.yml']}) optiondescription_1 = OptionDescription(name="firefox", doc="firefox", group_type=groups.namespace, children=[option_2, optiondescription_3, option_12, option_13, option_14, option_15, optiondescription_16], properties=frozenset({"basic"}), informations={'dictionaries': ['']}) option_22 = StrOption(name="title", doc="Title or Description", multi=True, default=["example"], properties=frozenset({"standard"}), informations={'type': 'string', 'fake_default': True, 'dictionaries': ['foxyproxy/00-foxyproxy.yml']}) option_23 = ChoiceOption(name="type", doc="Proxy Type", values=("HTTP", "HTTPS/SSL", "SOCKS4", "SOCKS5", "PAC URL", "WPAD", "System (use system settings)", "Direct (no proxy)"), multi=True, default_multi="Direct (no proxy)", properties=frozenset({"mandatory", "standard"}), informations={'type': 'choice', 'dictionaries': ['foxyproxy/00-foxyproxy.yml']}) option_24 = Regexp_option_24(name="color", doc="Color", multi=True, default=Calculation(func['jinja_to_function'], Params((), kwargs={'__internal_jinja': ParamValue("default_foxyproxy.proxies.color"), '__internal_type': ParamValue("regexp"), '__internal_multi': ParamValue(False), '__internal_files': ParamValue(['foxyproxy/00-foxyproxy.yml']), '__internal_attribute': ParamValue("default"), '__internal_variable': ParamValue("foxyproxy.proxies.color")})), properties=frozenset({"basic", "force_store_value", "mandatory"}), informations={'type': 'regexp', 'default_calculation_type': 'jinja', 'default_calculation': 'random color value', 'dictionaries': ['foxyproxy/00-foxyproxy.yml']}) option_25 = DomainnameOption(name="address", doc="IP address, DNS name, server name", multi=True, default=Calculation(func['jinja_to_function'], Params((), kwargs={'__internal_jinja': ParamValue("default_foxyproxy.proxies.address"), '__internal_type': ParamValue("domainname"), '__internal_multi': ParamValue(False), '__internal_files': ParamValue(['foxyproxy/00-foxyproxy.yml']), '__internal_attribute': ParamValue("default"), '__internal_variable': ParamValue("foxyproxy.proxies.address"), 'firefox.manual.http_proxy.address': ParamOption(option_5, notraisepropertyerror=True)})), type="domainname", allow_ip=True, allow_without_dot=True, properties=frozenset({"mandatory", "standard", Calculation(func['jinja_to_property'], Params((ParamValue("disabled")), kwargs={'__internal_jinja': ParamValue("disabled_foxyproxy.proxies.address"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(False), '__internal_files': ParamValue(['foxyproxy/00-foxyproxy.yml']), '__internal_attribute': ParamValue("disabled"), '__internal_variable': ParamValue("foxyproxy.proxies.address"), 'when': ParamValue(True), 'inverse': ParamValue(False), '_.type': ParamOption(option_23, notraisepropertyerror=True)}), help_function=func['jinja_to_property_help'])}), informations={'type': 'domainname', 'default_calculation_type': 'jinja', 'default_calculation': 'copy HTTP address if proxy is not "Manual"', 'dictionaries': ['foxyproxy/00-foxyproxy.yml'], 'disabled_calculation_type': 'jinja', 'disabled_calculation': 'if type not in:\n- HTTP\n- HTTPS/SSL\n- SOCKS4\n- SOCKS5\n'}) option_26 = PortOption(name="port", doc="Port", multi=True, default=Calculation(func['jinja_to_function'], Params((), kwargs={'__internal_jinja': ParamValue("default_foxyproxy.proxies.port"), '__internal_type': ParamValue("port"), '__internal_multi': ParamValue(False), '__internal_files': ParamValue(['foxyproxy/00-foxyproxy.yml']), '__internal_attribute': ParamValue("default"), '__internal_variable': ParamValue("foxyproxy.proxies.port"), 'firefox.manual.http_proxy.port': ParamOption(option_6, notraisepropertyerror=True)})), allow_private=True, properties=frozenset({"mandatory", "standard", Calculation(func['jinja_to_property'], Params((ParamValue("disabled")), kwargs={'__internal_jinja': ParamValue("disabled_foxyproxy.proxies.port"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(False), '__internal_files': ParamValue(['foxyproxy/00-foxyproxy.yml']), '__internal_attribute': ParamValue("disabled"), '__internal_variable': ParamValue("foxyproxy.proxies.port"), 'when': ParamValue(True), 'inverse': ParamValue(False), '_.type': ParamOption(option_23, notraisepropertyerror=True)}), help_function=func['jinja_to_property_help'])}), informations={'type': 'port', 'default_calculation_type': 'jinja', 'default_calculation': 'copy HTTP port if proxy is not "Manual"', 'dictionaries': ['foxyproxy/00-foxyproxy.yml'], 'disabled_calculation_type': 'jinja', 'disabled_calculation': 'if type not in:\n- HTTP\n- HTTPS/SSL\n- SOCKS4\n- SOCKS5\n'}) option_27 = UsernameOption(name="username", doc="Username", multi=True, properties=frozenset({"standard", Calculation(func['jinja_to_property'], Params((ParamValue("disabled")), kwargs={'__internal_jinja': ParamValue("disabled_foxyproxy.proxies.username"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(False), '__internal_files': ParamValue(['foxyproxy/00-foxyproxy.yml']), '__internal_attribute': ParamValue("disabled"), '__internal_variable': ParamValue("foxyproxy.proxies.username"), 'when': ParamValue(True), 'inverse': ParamValue(False), '_.type': ParamOption(option_23, notraisepropertyerror=True)}), help_function=func['jinja_to_property_help'])}), informations={'type': 'unix_user', 'dictionaries': ['foxyproxy/00-foxyproxy.yml', 'foxyproxy/10-redefine.yml'], 'disabled_calculation_type': 'jinja', 'disabled_calculation': 'if type not in:\n- HTTP\n- HTTPS/SSL\n- SOCKS4\n- SOCKS5\n'}) option_28 = PasswordOption(name="password", doc="Password", multi=True, properties=frozenset({"force_default_on_freeze", "standard", Calculation(func['jinja_to_property'], Params((ParamValue("hidden")), kwargs={'__internal_jinja': ParamValue("hidden_foxyproxy.proxies.password"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(False), '__internal_files': ParamValue(['foxyproxy/10-redefine.yml']), '__internal_attribute': ParamValue("hidden"), '__internal_variable': ParamValue("foxyproxy.proxies.password"), 'when': ParamValue(True), 'inverse': ParamValue(False), '_.username': ParamOption(option_27, notraisepropertyerror=True)}), help_function=func['jinja_to_property_help']), Calculation(func['jinja_to_property'], Params((ParamValue("disabled")), kwargs={'__internal_jinja': ParamValue("disabled_foxyproxy.proxies.password"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(False), '__internal_files': ParamValue(['foxyproxy/00-foxyproxy.yml']), '__internal_attribute': ParamValue("disabled"), '__internal_variable': ParamValue("foxyproxy.proxies.password"), 'when': ParamValue(True), 'inverse': ParamValue(False), '_.type': ParamOption(option_23, notraisepropertyerror=True)}), help_function=func['jinja_to_property_help']), Calculation(func['jinja_to_property'], Params((ParamValue("frozen")), kwargs={'__internal_jinja': ParamValue("frozen_foxyproxy.proxies.password"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(False), '__internal_files': ParamValue(['foxyproxy/10-redefine.yml']), '__internal_attribute': ParamValue("frozen"), '__internal_variable': ParamValue("foxyproxy.proxies.password"), 'when': ParamValue(True), 'inverse': ParamValue(False), '_.username': ParamOption(option_27, notraisepropertyerror=True)}), help_function=func['jinja_to_property_help'])}), informations={'type': 'secret', 'dictionaries': ['foxyproxy/00-foxyproxy.yml', 'foxyproxy/10-redefine.yml'], 'hidden_calculation_type': 'jinja', 'hidden_calculation': 'if username is not defined', 'disabled_calculation_type': 'jinja', 'disabled_calculation': 'if type not in:\n- HTTP\n- HTTPS/SSL\n- SOCKS4\n- SOCKS5\n'}) option_29 = URLOption(name="url", doc="URL", multi=True, default=Calculation(func['jinja_to_function'], Params((), kwargs={'__internal_jinja': ParamValue("default_foxyproxy.proxies.url"), '__internal_type': ParamValue("web_address"), '__internal_multi': ParamValue(False), '__internal_files': ParamValue(['foxyproxy/00-foxyproxy.yml']), '__internal_attribute': ParamValue("default"), '__internal_variable': ParamValue("foxyproxy.proxies.url"), 'firefox.auto': ParamOption(option_12, notraisepropertyerror=True)})), allow_ip=False, allow_without_dot=True, properties=frozenset({"mandatory", "standard", Calculation(func['jinja_to_property'], Params((ParamValue("disabled")), kwargs={'__internal_jinja': ParamValue("disabled_foxyproxy.proxies.url"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(False), '__internal_files': ParamValue(['foxyproxy/00-foxyproxy.yml']), '__internal_attribute': ParamValue("disabled"), '__internal_variable': ParamValue("foxyproxy.proxies.url"), 'when': ParamValue(True), 'inverse': ParamValue(False), '_.type': ParamOption(option_23, notraisepropertyerror=True)}), help_function=func['jinja_to_property_help'])}), informations={'type': 'web_address', 'default_calculation_type': 'jinja', 'default_calculation': 'copy HTTP address if proxy is "Auto"', 'dictionaries': ['foxyproxy/00-foxyproxy.yml'], 'disabled_calculation_type': 'jinja', 'disabled_calculation': 'if type is not in:\n- PAC URL\n- WPAD\n'}) optiondescription_21 = Leadership(name="proxies", doc="Proxy configuration", children=[option_22, option_23, option_24, option_25, option_26, option_27, option_28, option_29], properties=frozenset({"basic"}), informations={'dictionaries': ['foxyproxy/00-foxyproxy.yml', 'foxyproxy/10-redefine.yml']}) optiondescription_20 = OptionDescription(name="foxyproxy", doc="foxyproxy", group_type=groups.namespace, children=[optiondescription_21], properties=frozenset({"basic"}), informations={'dictionaries': ['']}) option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1, optiondescription_20]) cfg = Config(option_0) cfg.property.read_write() def _regen(*args): print(args) def v(parent, out, level=0): sublevel = level + 1 for key, value in parent.items(): if key.isoptiondescription(): out.content = HTML(f'{key.description()}') v(value, out, sublevel) else: option_type = key.information.get('type') if option_type == 'choice': options = [] for choice in key.value.list(): if choice == value: selected = ' selected' else: selected = '' options.append(f'') html = HTML(f'{key.description()}: ') out.content = html # input_ = document.querySelector(f"#{key.path()}") # print(input_) # input_.onchange = on_change html.onchange = regen elif option_type == 'boolean': if value: checked = ' checked' else: checked = '' out.content = HTML(f'{key.description()}: ') else: if value is None: value = '' out.content = HTML(f'{key.description()}: ') out = pydom["#result"][0] out.html = '' v(cfg.value.get(), out) async def regen(*args): print(args) _regen() #proxy = create_proxy(regen) #document.body.addEventListener("click", proxy) _regen()