Metadata-Version: 1.2
Name: micropython-structured-config
Version: 2.2
Summary: Configuration file support for micropython where the config structure is solely defined in python.
Home-page: https://gitlab.com/alelec/micropython-structured-config
Author: Andrew Leech
Author-email: andrew@alelec.net
Maintainer: Andrew Leech
Maintainer-email: andrew@alelec.net
License: MIT
Description: Structured Config for Micropython
        =================================
        
        A configuration module for python where the config structure is solely
        defined in python with automatic reading & writing to disk and field
        validation.
        
        This package provides a micropython port of
        https://gitlab.com/alelec/structured\_config with support for json
        storage files.
        
        Background
        ----------
        
        There are lots of different modules and formats available for creating
        configuration files in a python project.
        
        All of the ones I've used in the past have one main limitations in
        common however; the primary definition of the configuration elements it
        either not written in python, or it's written in something like a python
        dict where you don't get particularly good static inspection of
        elements.
        
        I personally like to do my python development in a smart ide like
        pycharm where I can take full advantage of inspection and
        auto-completion. If your config is not written in python however, I
        don't get to do this.
        
        If you want any kind of introspection of config files, you end up having
        some kind of python parser of the config file with all the configuration
        elements repeated in both the default template and in some kind of
        mirror class. This module aims to remove this limitation.
        
        Requirements
        ------------
        
        ``structured_config`` depends on some features included in micropython
        v1.13 so you'll want to be using that at a minimum.
        
        It also needs the ``MICROPY_PY_DELATTR_SETATTR`` build setting enabled.
        This is included by default on stm32 port, but for other ports you will
        need a custom build with this enabled.
        
        Basic Usage
        -----------
        
        With ``structured_config``, your ``config.py`` file in your project can
        be something like:
        
        ::
        
            from structured_config import ConfigFile, Structure
        
            class Config(Structure):
        
                class server(Structure):
                    url = 'https:www.example.com'
                    username = '<user>'
                    password = '<password>'
        
        
                # Max number of tcp connections at any one time
                concurrent_connections =  32
        
                # Local service port
                service_port = 45080
        
        
            config = Config('/path/to/config.json')
        
        Any other modules in your project can then simply
        
        ::
        
            from config import config
        
            import requests
            from requests.auth import HTTPBasicAuth
        
            r = requests.get(config.server.url, auth=HTTPBasicAuth(config.server.username, config.server.password))
        
        and so on. Your IDE should give you full autocomplete on all these
        elements, becuase as far as it knows your config is a normal class with
        normal static attributes. If you want to change these config items in
        code it's as simple as setting the attribute
        
        ::
        
            from config import config
        
            config.concurrent_connections = 64
        
            config.__save__()
        
        That's it. The config is written to disk in the json file pointed to in
        Config() instantiation
        
        Lists of elements
        -----------------
        
        If you want a slightly more complex config file with a list of elements,
        this can be handled too
        
        ::
        
            import structured_config
            from structured_config import Structure, ConfigFile
        
            # Pre-define the object we want to store a list of.
            class Map(Structure):
                remote_path = None
                local_path = None
        
        
            # Default configuration for the application
            class Config(Structure):
        
                class server(Structure):
                    url = 'https:www.example.com'
                    username = '<user>'
                    password = '<password>'
        
                mapping = [
                    Map(
                        remote_path="/test/",
                        local_path="~/test/"
                    ),
                    Map(
                        remote_path="/one/",
                        local_path="~/two/"
                    ),
                    Map(
                        remote_path="/two/",
                        local_path="~/one/"
                    )
                ]
        
            config = Config('config.json')
        
        Your main code can access the Map items in the list by all the normal
        means. if you append() new ones onto the list or pop() old ones off the
        list, the config will automatically write them to disk. Same goes for
        editing either of the attributes in any of the Map objects that have
        been added to the list.
        
        The type of element added to the list can be enforced / validated too,
        eg
        
        ::
        
            import structured_config
            from structured_config import Structure, ConfigFile, List
        
            # Pre-define the object we want to store a list of.
            class Map(Structure):
                remote_path = None
                local_path = None
        
        
            # Default configuration for the application
            class Config(Structure):
        
                class server(Structure):
                    url = 'https:www.example.com'
                    username = '<user>'
                    password = '<password>'
        
                mapping = List([
                    Map(
                        remote_path="/test/",
                        local_path="~/test/"
                    ),
                    Map(
                        remote_path="/one/",
                        local_path="~/two/"
                    ),
                    Map(
                        remote_path="/two/",
                        local_path="~/one/"
                    )
                ], type=Map)
        
            config = Config('config.json')
        
        Now when creating a new instance, loading from file or even just
        appending to the list, the type will be checked to ensure it matches the
        declaration.
        
        Dictionaries of elements
        ------------------------
        
        Similar to the List above, a Dict of elements can be defined where the
        type of the values in the dict can be controlled
        
        ::
        
            import structured_config
            from structured_config import Structure, ConfigFile, Dict
        
            # Pre-define the object we want to store a list of.
            class Map(Structure):
                remote_path = None
                local_path = None
        
            # Default configuration for the application
            class Config(Structure):
        
                mapping = Dict({
                    "test": Map(remote_path="/test/", local_path="~/test/"),
                    }, type=Map)
        
            config = Config('config.json')
            config.mapping['new'] = Map(remote_path='c:\\new', local_path='~/new')
        
            # Will raise an exception as the value is incorrect!
            config.mapping['fails'] = "Nope"
        
        Format convertions and validations
        ----------------------------------
        
        If you want to enforce the type of some attributes, we've got that
        covered as well:
        
        ::
        
            from structured_config import ConfigFile, Structure, TypedField, IntField
        
            class config(Structure):
        
                concurrent_connections = IntField(32)
        
                path = TypedField('$HOME', os.path.expandvars)
        
        
            config = Config('config.json')
        
        Some examples of available TypeFields include: \* IntField : converts to
        int() \* FloatField : converts to float() \* StrField : converts to
        str() \* PathField : converts to pathlib.Path()
        
        Others can be created on demand by using
        ``TypeField(value, converter_funtion)`` or by subclassing TypeField as
        per the ones above.
        
        Any time a config attribute is set, it will be passed through the
        validation function first. The raw (unconverted) value will be saved to
        disk.
        
        Get's on the config objects attribute return the converted value, not
        the Field object.
        
        Field documentation
        -------------------
        
        Once you're using ``Field()`` types to define your elements you can
        document them too :
        
        ::
        
            from structured_config import ConfigFile, Structure, TypedField, IntField
        
            class config(Structure):
        
                concurrent_connections = IntField(32)            | "The number of connections allowed"
                path = TypedField('$HOME', os.path.expandvars)   | "User's home directory"
        
        
            config = Config('config.json')
        
        These can be accessed in code via
        ``Config.__fdoc__('concurrent_connections')``
        
Platform: UNKNOWN
