Metadata-Version: 2.1
Name: managedstate
Version: 2.1.0
Summary: State management inspired by Redux
Home-page: https://github.com/immijimmi/managedstate
Author: immijimmi
Author-email: imranhamid99@msn.com
License: MIT
Download-URL: https://github.com/immijimmi/managedstate/archive/refs/tags/v2.1.0.tar.gz
Description: # managedstate
        
        ###### State management inspired by Redux
        
        ## Quickstart
        
        ### Setup
        
        ```python
        from managedstate import State
        
        initial_state = {
            "first_key": [
                {
                    "id": 1,
                    "second_key": True
                },
                {
                    "id": 2,
                    "second_key": False
                }
            ]
        }
        
        state = State(initial_state=initial_state)
        ```
        
        ### Getting the state
        
        - The full state object
        ```python
        >>> state.get()
        {'first_key': [{'id': 1, 'second_key': True}, {'id': 2, 'second_key': False}]}
        ```
        
        - A sub-state object
        ```python
        >>> state.get(["first_key", 0, "second_key"], defaults=[[], {}, False])
        True
        ```
        
        - A sub-state object, using a query function
        ```python
        def id_is_1_query(first_key_list):
            for index, obj in enumerate(first_key_list):
                if obj["id"] == 1:
                    return index
        ```
        ```python
        >>> state.get(["first_key", KeyQuery(id_is_1_query), "second_key"], defaults=[[], {}, False])
        True
        ```
        
        ### Setting the state
        - The full state object
        ```python
        >>> state.set({'first_key': [{'id': 3, 'second_key': True}, {'id': 4, 'second_key': False}]})
        >>> state.get()
        {'first_key': [{'id': 3, 'second_key': True}, {'id': 4, 'second_key': False}]}
        ```
        
        - A sub-state object, using a query function
        ```python
        def get_id_key_query(target_id):  # This will dynamically create the query we need, when we need it
            def id_query(substate):
                for index, obj in enumerate(substate):
                    if obj["id"] == target_id:
                        return index
            return KeyQuery(id_query)
        ```
        ```python
        >>> state.set(False, ['first_key', get_id_key_query(3), 'second_key'], defaults=[[], {}])
        >>> state.get()
        {'first_key': [{'id': 3, 'second_key': False}, {'id': 4, 'second_key': False}]}
        ```
        
        
        ## Functionality
        
        ### Dependencies
        
        The State class and the extensions in this package implement Extendable and Extension respectively, from [objectextensions](https://github.com/immijimmi/objectextensions).
        As such, applying extensions is done by calling the class method `State.with_extensions()` and passing in the extension classes to be applied.
        
        Example code:
        ```python
        from managedstate import State
        from managedstate.extensions import Registrar
        
        state = State.with_extensions(Registrar)()
        ```
        
        ### Extensions
        
        *extensions*.**Registrar**  
        &nbsp;&nbsp;&nbsp;&nbsp;Allows specific get and set operations to be registered under a shorthand label for ease of use later.  
        &nbsp;
        
        *extensions*.**Listeners**  
        &nbsp;&nbsp;&nbsp;&nbsp;Provides an easy way to attach observer methods that will be called immediately after `set()` and/or `get()`.  
        &nbsp;
        
        ### Data Classes
        
        **AttributeName**(*self, attribute_name: str*)  
        &nbsp;&nbsp;&nbsp;&nbsp;An instance of this class should be provided as a path key when getting or setting the state,  
        &nbsp;&nbsp;&nbsp;&nbsp;to indicate that the next nesting level of the state should be accessed via an object attribute.  
        
        *Note: As this class is used indirectly to determine the method of access into the state,*  
        &nbsp;&nbsp;&nbsp;&nbsp;*it should never be stored directly as a key within that state.*  
        &nbsp;
        
        **KeyQuery**(*self, path_key_getter: Callable[[Any], Any]*)  
        &nbsp;&nbsp;&nbsp;&nbsp;Instances of this class can be provided as path keys when getting or setting the state,  
        &nbsp;&nbsp;&nbsp;&nbsp;to indicate that the next nesting level of the state should be accessed via the path key returned  
        &nbsp;&nbsp;&nbsp;&nbsp;from its stored function.  
        &nbsp;&nbsp;&nbsp;&nbsp;The function will receive a copy of the state object at the current level of nesting  
        &nbsp;&nbsp;&nbsp;&nbsp;in order to determine what key to return.  
        &nbsp;
        
        *extensions*.**PartialQuery**(*self, path_key_getter: Callable[[Any], Any]*)  
        &nbsp;&nbsp;&nbsp;&nbsp;Instances of this class can be provided as path keys only in `Registrar.register_path()`.  
        &nbsp;&nbsp;&nbsp;&nbsp;When `registered_get()`/`registered_set()` is called with the relevant path label, the function provided below  
        &nbsp;&nbsp;&nbsp;&nbsp;will be called and passed one value from the custom query args list;  
        &nbsp;&nbsp;&nbsp;&nbsp;a valid path key or KeyQuery should be returned.  
        &nbsp;
        
        ### Properties
        
        *extensions*.Registrar.**registered_paths**  
        &nbsp;&nbsp;&nbsp;&nbsp;Returns a copy of the current path registry.  
        &nbsp;
        
        ### Methods
        
        State.**get**(*self, path_keys: Sequence[Any] = (), defaults: Sequence[Any] = ()*)  
        &nbsp;&nbsp;&nbsp;&nbsp;Drills into the state object using the provided path keys in sequence.  
        &nbsp;&nbsp;&nbsp;&nbsp;Any time progressing further into the state object fails, the default value at the relevant index of defaults  
        &nbsp;&nbsp;&nbsp;&nbsp;is substituted in.  
        &nbsp;&nbsp;&nbsp;&nbsp;Returns a copy of the drilled-down state object.  
        &nbsp;
        
        State.**set**(*self, value: Any, path_keys: Sequence[Any] = (), defaults: Sequence[Any] = ()*)  
        &nbsp;&nbsp;&nbsp;&nbsp;Drills into the state object using the provided path keys in sequence.  
        &nbsp;&nbsp;&nbsp;&nbsp;Any time progressing further into the state object fails, the default value at the relevant index of defaults  
        &nbsp;&nbsp;&nbsp;&nbsp;is substituted in.  
        &nbsp;&nbsp;&nbsp;&nbsp;The final path key is used as the index to store a copy of the provided value at  
        &nbsp;&nbsp;&nbsp;&nbsp;inside the drilled-down state object.  
        &nbsp;
        
        *extensions*.Registrar.**register_path**(*self, registered_path_label: str, path_keys: Sequence[Any], defaults: Sequence[Any] = ()*)  
        &nbsp;&nbsp;&nbsp;&nbsp;Saves the provided path keys and defaults under the provided label, so that a custom get or set can be  
        &nbsp;&nbsp;&nbsp;&nbsp;carried out at later times simply by providing the label again in a call to `registered_get()` or `registered_set()`.  
        &nbsp;
        
        *extensions*.Registrar.**get_shape**(*self, initial_state: Any = None*)  
        &nbsp;&nbsp;&nbsp;&nbsp;Generates a default shape for the state, using the current registered paths.  
        &nbsp;&nbsp;&nbsp;&nbsp;  
        &nbsp;&nbsp;&nbsp;&nbsp;Any registered paths containing PartialQuery objects are truncated for this purpose, as it is not possible  
        &nbsp;&nbsp;&nbsp;&nbsp;to determine what kind of value a PartialQuery object would provide to drill further into the state.  
        &nbsp;
        
        *extensions*.Registrar.**registered_get**(*self, registered_path_label: str, custom_query_args: Sequence[Any] = ()*)  
        &nbsp;&nbsp;&nbsp;&nbsp;Calls `get()`, passing in the path keys and defaults previously provided in `register()`.  
        &nbsp;&nbsp;&nbsp;&nbsp;If any of these path keys are instances of PartialQuery, each will be called and passed one value from  
        &nbsp;&nbsp;&nbsp;&nbsp;the custom query args list and is expected to return a valid path key or KeyQuery.  
        &nbsp;
        
        *extensions*.Registrar.**registered_set**(*self, value: Any, registered_path_label: str, custom_query_args: Sequence[Any] = ()*)  
        &nbsp;&nbsp;&nbsp;&nbsp;Calls `set()`, passing in the path keys and defaults previously provided in `register()`.  
        &nbsp;&nbsp;&nbsp;&nbsp;If any of these path keys are instances of PartialQuery, each will be called and passed one value from  
        &nbsp;&nbsp;&nbsp;&nbsp;the custom query args list and is expected to return a valid path key or KeyQuery.  
        &nbsp;
        
        *extensions*.Listeners.**add_listener**(*self, method: str, listener: Callable[[dict], None]*)  
        &nbsp;&nbsp;&nbsp;&nbsp;Adds the provided listener to a set of callbacks for the specified method.  
        &nbsp;&nbsp;&nbsp;&nbsp;These callbacks will receive copies of the method return value and its arguments  
        &nbsp;&nbsp;&nbsp;&nbsp;in the form `result, self, *args, **kwargs`.  
        &nbsp;
        
        *extensions*.Listeners.**remove_listener**(*self, method: str, listener: Callable[[dict], None]*)  
        &nbsp;&nbsp;&nbsp;&nbsp;Removes the provided listener from the set of callbacks for the specified method.  
        &nbsp;
        
        ### Additional Info
        
        - KeyQuery instances provided as path keys can return any valid path key, *except* another KeyQuery or a PartialQuery.
        - Similarly, PartialQuery instances can return any valid path key except for another PartialQuery (they can however return a KeyQuery)
        - The data classes provided in this package are not designed to be stored inside the state object themselves, and as such their `__hash__` methods have been removed.
        
Keywords: state,managed,management,access,data
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.8
Description-Content-Type: text/markdown
