managedstate


Namemanagedstate JSON
Version 5.1.0 PyPI version JSON
download
home_pagehttps://github.com/immijimmi/managedstate
SummaryState management inspired by Redux
upload_time2023-09-25 05:29:19
maintainer
docs_urlNone
authorimmijimmi
requires_python
licenseMIT
keywords state managed management access data
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # 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**  
    Allows specific get and set operations to be registered under a shorthand label for ease of use later.  
 

*extensions*.**Listeners**  
    Provides an easy way to attach observer methods that will be called immediately after `set()` and/or `get()`.  
 

### Data Classes

**AttributeName**(*self, attribute_name: str*)  
    An instance of this class should be provided as a path key when getting or setting the state,  
    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,*  
    *it should never be stored directly as a key within that state.*  
 

**KeyQuery**(*self, path_key_getter: Callable[[Any], Any]*)  
    Instances of this class can be provided as path keys when getting or setting the state,  
    to indicate that the next nesting level of the state should be accessed via the path key returned  
    from its stored function.  
    The function will receive a copy of the state object at the current level of nesting  
    in order to determine what key to return.  
 

*extensions*.**PartialQuery**(*self, path_key_getter: Callable[[Any], Any]*)  
    Instances of this class can be provided as path keys only in `Registrar.register_path()`.  
    When `registered_get()`/`registered_set()` is called with the relevant path label, the function provided below  
    will be called and passed one value from the custom query args list;  
    a valid path key or KeyQuery should be returned.  
 

### Properties

*extensions*.Registrar.**registered_paths**  
    Returns a copy of the current path registry.  
 

### Methods

State.**get**(*self, path_keys: Iterable[Any] = (), defaults: Iterable[Any] = ()*)  
    Drills into the state object using the provided path keys in sequence.  
    Any time progressing further into the state object fails, a copy of the default value at the relevant index  
    of defaults is substituted in.  
    Returns a copy of the drilled-down state object.  
      
    The `defaults` param may be provided any number of default values, and they will only be used as necessary.  
 

State.**set**(*self, value: Any, path_keys: Iterable[Any] = (), defaults: Iterable[Any] = ()*)  
    Drills into the state object using the provided path keys in sequence.  
    Any time progressing further into the state object fails, a copy of the default value at the relevant index  
    of defaults is substituted in.  
    The final path key is used as the index to store a copy of the provided value at  
    inside the drilled-down state object.  
      
    The `defaults` param may be provided any number of default values, and they will only be used as necessary.  
 

*extensions*.Registrar.**register_path**(*self, registered_path_label: str, path_keys: Iterable[Any], defaults: Iterable[Any] = ()*)  
    Saves the provided path keys and defaults under the provided label, so that a custom get or set can be  
    carried out at later times simply by providing the label again in a call to `registered_get()` or `registered_set()`.  
 

*extensions*.Registrar.**get_shape**(*self, initial_state: Any = None*)  
    Generates a default shape for the state, using the current registered paths.  
      
    Any registered paths containing PartialQuery objects are truncated for this purpose, as it is not possible  
    to determine what kind of value a PartialQuery object would provide to drill further into the state.  
 

*extensions*.Registrar.**registered_get**(*self, registered_path_label: str, custom_query_args: Iterable[Any] = ()*)  
    Calls `get()`, passing in the path keys and defaults previously provided in `register()`.  
    If any of these path keys are instances of PartialQuery, each will be called and passed one value from  
    the custom query args list and is expected to return a valid path key or KeyQuery.  
 

*extensions*.Registrar.**registered_set**(*self, value: Any, registered_path_label: str, custom_query_args: Iterable[Any] = ()*)  
    Calls `set()`, passing in the path keys and defaults previously provided in `register()`.  
    If any of these path keys are instances of PartialQuery, each will be called and passed one value from  
    the custom query args list and is expected to return a valid path key or KeyQuery.  
 

*extensions*.Listeners.**add_listener**(*self, method_name: str, listener: Callable[[dict], None]*)  
    Adds the provided listener to a set of callbacks for the specified method.  
    These callbacks will receive copies of the method return value and its arguments  
    in the form `result, self, *args, **kwargs`.  
 

*extensions*.Listeners.**remove_listener**(*self, method_name: str, listener: Callable[[dict], None]*)  
    Removes the provided listener from the set of callbacks for the specified method.  
 

### 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. Doing so may result in unintended behaviour

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/immijimmi/managedstate",
    "name": "managedstate",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "state,managed,management,access,data",
    "author": "immijimmi",
    "author_email": "immijimmi1@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/2d/03/409c1df9e78877ca97fbdf2eb20897e5ede6657fbe29bf68304521ec19cc/managedstate-5.1.0.tar.gz",
    "platform": null,
    "description": "# managedstate\r\n\r\n###### State management inspired by Redux\r\n\r\n## Quickstart\r\n\r\n### Setup\r\n\r\n```python\r\nfrom managedstate import State\r\n\r\ninitial_state = {\r\n    \"first_key\": [\r\n        {\r\n            \"id\": 1,\r\n            \"second_key\": True\r\n        },\r\n        {\r\n            \"id\": 2,\r\n            \"second_key\": False\r\n        }\r\n    ]\r\n}\r\n\r\nstate = State(initial_state=initial_state)\r\n```\r\n\r\n### Getting the state\r\n\r\n- The full state object\r\n```python\r\n>>> state.get()\r\n{'first_key': [{'id': 1, 'second_key': True}, {'id': 2, 'second_key': False}]}\r\n```\r\n\r\n- A sub-state object\r\n```python\r\n>>> state.get([\"first_key\", 0, \"second_key\"], defaults=[[], {}, False])\r\nTrue\r\n```\r\n\r\n- A sub-state object, using a query function\r\n```python\r\ndef id_is_1_query(first_key_list):\r\n    for index, obj in enumerate(first_key_list):\r\n        if obj[\"id\"] == 1:\r\n            return index\r\n```\r\n```python\r\n>>> state.get([\"first_key\", KeyQuery(id_is_1_query), \"second_key\"], defaults=[[], {}, False])\r\nTrue\r\n```\r\n\r\n### Setting the state\r\n- The full state object\r\n```python\r\n>>> state.set({'first_key': [{'id': 3, 'second_key': True}, {'id': 4, 'second_key': False}]})\r\n>>> state.get()\r\n{'first_key': [{'id': 3, 'second_key': True}, {'id': 4, 'second_key': False}]}\r\n```\r\n\r\n- A sub-state object, using a query function\r\n```python\r\ndef get_id_key_query(target_id):  # This will dynamically create the query we need, when we need it\r\n    def id_query(substate):\r\n        for index, obj in enumerate(substate):\r\n            if obj[\"id\"] == target_id:\r\n                return index\r\n    return KeyQuery(id_query)\r\n```\r\n```python\r\n>>> state.set(False, ['first_key', get_id_key_query(3), 'second_key'], defaults=[[], {}])\r\n>>> state.get()\r\n{'first_key': [{'id': 3, 'second_key': False}, {'id': 4, 'second_key': False}]}\r\n```\r\n\r\n\r\n## Functionality\r\n\r\n### Dependencies\r\n\r\nThe State class and the extensions in this package implement Extendable and Extension respectively, from [objectextensions](https://github.com/immijimmi/objectextensions).\r\nAs such, applying extensions is done by calling the class method `State.with_extensions()` and passing in the extension classes to be applied.\r\n\r\nExample code:\r\n```python\r\nfrom managedstate import State\r\nfrom managedstate.extensions import Registrar\r\n\r\nstate = State.with_extensions(Registrar)()\r\n```\r\n\r\n### Extensions\r\n\r\n*extensions*.**Registrar**  \r\n    Allows specific get and set operations to be registered under a shorthand label for ease of use later.  \r\n \r\n\r\n*extensions*.**Listeners**  \r\n    Provides an easy way to attach observer methods that will be called immediately after `set()` and/or `get()`.  \r\n \r\n\r\n### Data Classes\r\n\r\n**AttributeName**(*self, attribute_name: str*)  \r\n    An instance of this class should be provided as a path key when getting or setting the state,  \r\n    to indicate that the next nesting level of the state should be accessed via an object attribute.  \r\n\r\n*Note: As this class is used indirectly to determine the method of access into the state,*  \r\n    *it should never be stored directly as a key within that state.*  \r\n \r\n\r\n**KeyQuery**(*self, path_key_getter: Callable[[Any], Any]*)  \r\n    Instances of this class can be provided as path keys when getting or setting the state,  \r\n    to indicate that the next nesting level of the state should be accessed via the path key returned  \r\n    from its stored function.  \r\n    The function will receive a copy of the state object at the current level of nesting  \r\n    in order to determine what key to return.  \r\n \r\n\r\n*extensions*.**PartialQuery**(*self, path_key_getter: Callable[[Any], Any]*)  \r\n    Instances of this class can be provided as path keys only in `Registrar.register_path()`.  \r\n    When `registered_get()`/`registered_set()` is called with the relevant path label, the function provided below  \r\n    will be called and passed one value from the custom query args list;  \r\n    a valid path key or KeyQuery should be returned.  \r\n \r\n\r\n### Properties\r\n\r\n*extensions*.Registrar.**registered_paths**  \r\n    Returns a copy of the current path registry.  \r\n \r\n\r\n### Methods\r\n\r\nState.**get**(*self, path_keys: Iterable[Any] = (), defaults: Iterable[Any] = ()*)  \r\n    Drills into the state object using the provided path keys in sequence.  \r\n    Any time progressing further into the state object fails, a copy of the default value at the relevant index  \r\n    of defaults is substituted in.  \r\n    Returns a copy of the drilled-down state object.  \r\n      \r\n    The `defaults` param may be provided any number of default values, and they will only be used as necessary.  \r\n \r\n\r\nState.**set**(*self, value: Any, path_keys: Iterable[Any] = (), defaults: Iterable[Any] = ()*)  \r\n    Drills into the state object using the provided path keys in sequence.  \r\n    Any time progressing further into the state object fails, a copy of the default value at the relevant index  \r\n    of defaults is substituted in.  \r\n    The final path key is used as the index to store a copy of the provided value at  \r\n    inside the drilled-down state object.  \r\n      \r\n    The `defaults` param may be provided any number of default values, and they will only be used as necessary.  \r\n \r\n\r\n*extensions*.Registrar.**register_path**(*self, registered_path_label: str, path_keys: Iterable[Any], defaults: Iterable[Any] = ()*)  \r\n    Saves the provided path keys and defaults under the provided label, so that a custom get or set can be  \r\n    carried out at later times simply by providing the label again in a call to `registered_get()` or `registered_set()`.  \r\n \r\n\r\n*extensions*.Registrar.**get_shape**(*self, initial_state: Any = None*)  \r\n    Generates a default shape for the state, using the current registered paths.  \r\n      \r\n    Any registered paths containing PartialQuery objects are truncated for this purpose, as it is not possible  \r\n    to determine what kind of value a PartialQuery object would provide to drill further into the state.  \r\n \r\n\r\n*extensions*.Registrar.**registered_get**(*self, registered_path_label: str, custom_query_args: Iterable[Any] = ()*)  \r\n    Calls `get()`, passing in the path keys and defaults previously provided in `register()`.  \r\n    If any of these path keys are instances of PartialQuery, each will be called and passed one value from  \r\n    the custom query args list and is expected to return a valid path key or KeyQuery.  \r\n \r\n\r\n*extensions*.Registrar.**registered_set**(*self, value: Any, registered_path_label: str, custom_query_args: Iterable[Any] = ()*)  \r\n    Calls `set()`, passing in the path keys and defaults previously provided in `register()`.  \r\n    If any of these path keys are instances of PartialQuery, each will be called and passed one value from  \r\n    the custom query args list and is expected to return a valid path key or KeyQuery.  \r\n \r\n\r\n*extensions*.Listeners.**add_listener**(*self, method_name: str, listener: Callable[[dict], None]*)  \r\n    Adds the provided listener to a set of callbacks for the specified method.  \r\n    These callbacks will receive copies of the method return value and its arguments  \r\n    in the form `result, self, *args, **kwargs`.  \r\n \r\n\r\n*extensions*.Listeners.**remove_listener**(*self, method_name: str, listener: Callable[[dict], None]*)  \r\n    Removes the provided listener from the set of callbacks for the specified method.  \r\n \r\n\r\n### Additional Info\r\n\r\n- KeyQuery instances provided as path keys can return any valid path key, *except* another KeyQuery or a PartialQuery\r\n- Similarly, PartialQuery instances can return any valid path key except for another PartialQuery (they can however return a KeyQuery)\r\n- The data classes provided in this package are not designed to be stored inside the state object themselves. Doing so may result in unintended behaviour\r\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "State management inspired by Redux",
    "version": "5.1.0",
    "project_urls": {
        "Download": "https://github.com/immijimmi/managedstate/archive/refs/tags/v5.1.0.tar.gz",
        "Homepage": "https://github.com/immijimmi/managedstate"
    },
    "split_keywords": [
        "state",
        "managed",
        "management",
        "access",
        "data"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "2d03409c1df9e78877ca97fbdf2eb20897e5ede6657fbe29bf68304521ec19cc",
                "md5": "475e9c2a86bfea69c54659642dc2a3c6",
                "sha256": "998c9c051520fb5fc120e4d59250373ec7b3ca4464a16f2ab6fb91e3715320d7"
            },
            "downloads": -1,
            "filename": "managedstate-5.1.0.tar.gz",
            "has_sig": false,
            "md5_digest": "475e9c2a86bfea69c54659642dc2a3c6",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 12312,
            "upload_time": "2023-09-25T05:29:19",
            "upload_time_iso_8601": "2023-09-25T05:29:19.781125Z",
            "url": "https://files.pythonhosted.org/packages/2d/03/409c1df9e78877ca97fbdf2eb20897e5ede6657fbe29bf68304521ec19cc/managedstate-5.1.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-09-25 05:29:19",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "immijimmi",
    "github_project": "managedstate",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "managedstate"
}
        
Elapsed time: 0.62947s