kabaret.flow-contextual-dict


Namekabaret.flow-contextual-dict JSON
Version 0.1.2 PyPI version JSON
download
home_pagehttps://gitlab.com/kabaretstudio/kabaret.flow_contextual_dict
Summarykabaret.flow contextual dict
upload_time2020-11-04 14:47:18
maintainer
docs_urlNone
authorDamien "dee" Coureau
requires_python>=2.7,!=3.0.*,!=3.1.*,!=3.2.*
licenseLGPLv3+
keywords vfx animation pipeline asset library
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # kabaret.flow_contextual_dict

This package provide the `ContextualView` class and the `get_contextual_dict` function.

Together, they give your flow users the ability to use defined value
anywhere in the branch underneeth and override those values where you 
see fit in the branches.

Everything is explained here, but if your of the kind that prefers to read and execute code, there is a demo flow in the package for that. Install the package an create a new project with the type `kabaret.flow_contextual_dict.demo_flow.DemoFlow`.

## Concept

Here is a quick example with this classic structure where `settings` are `ContextualView` Objects:
```
Project
    settings
    episodes
        ep001
            settings
            sequences
                seq001
                    settings
                    shots
                        shot001
                            settings
                            anim
                                settings
                                init_action
                                bake_action
                            lighting
                                settings
                                init_action
                                render_action
                            comp
                                settings
                                init_action
                                render_action
                        shot002
                seq002
                    ...
        ep002
            ...
```
Let's say in the `Project.settings` defines `fps=24` and a `pool="ANY"`.
Every object in the episodes branch can call `get_contextual_dict()` to receive a dict like `{fps:24, pool:"ANY"}`.
Most likely, action of every step/department of every shot will use this.

Now let's say the sequence `seq002` is in a hurry and you want to dispatch all actions on your farm's "SUPER_COMPUTERS" pool. All you need is to "override" with `pool="SUPER_COMPUTERS"` in `ep002.settings`.

You can do this in each `settings` in the flow, and you can also "add" values in each of them (those "overrides" and "adds" are called "edits").

In a nutshell, it's a cascading dict, or as some call it: a **contextual dict**.

## Install

`pip install kabaret.flow_contextual_dict`

Please use a virtual env, it is good for you and your karma ^^

## Usage

### Defining Contexts

In order to add a contextual dict in your flow, you just need to add
a Child relation to a `ContextualView`:
```
class Shot(flow.Object):

    settings = flow.Child(contextualView)
    ...

```

The name of the relation is very important:
- Overrides stacking is based on this name so you need to use the same
name along your branch in order for overrides to work as expected.
- It defines the "context_name" argument to use for `get_contextual_dict()` calls.

So this will not work:
```
Project
    settings
    episodes
        ep001
            episode_settings
```
But this will:
```
Project 
    settings
    episodes
        ep001
            settings
```
Note that you can use `Child().ui(label="Episode Settings")` if you *really* want to display a different name in the GUI.

This gives the ability to use several contexts in the same flow.
In this structure, all * marked item are `ContextualView`. There is two
context defined: `settings` and `config`. The first one drives values by `sequences` and `shots`, the second one only affects `episodes`.
```
Project
    settings *
    config *
    episodes
        ep001
        config *
        sequences
            seq001
                settings *
                shots
                    shot001
                        settings *
```

### Editing Context Values

Once your flow is salted with `ContextualView`, the user will be able to
add value using the *"Add"* action and to edit values by double clicking on them.

If you want, for debug or inquiry, you can inspect the edits done thru a `ContectualView` by using its "Show Edits" actions. It will bring you to
a page showing only values defined here. Double-clicking one of those items
will show you more information, especially **the history of modification** for this value (what changed, who did it, and when).
You will also be able to change the override value, as well as disable/enable it.

You can also programatically edit the context by defining `get_default_contextual_edits(context_name)` methods returning a dict of value to use if no override exists for them.

In other words: user edits made with `ContextualView` actions will override values returned by a local or upstream `get_default_contextual_edits()` method.

### Using Context Values

In order to get a context dict, you just need to call `get_contextual_dict(leaf, context_name)`. The `leaf` is the point in the branch where you want the value to be evaluated. It will most of the time be `self`. 

Here is an example in an Action.run():
```
class SubmitRender(flow.Action):

    render_settings = flow.Child(ContextualView)

    def run(self, button):
        if button == 'Confirm':
            context = get_contextual_dict(
                self, 'render_settings'
            )
            my_dispatcher.submit(
                scene=self.get_scene_path(),
                fps=context.get('fps', 24),
                pool=context.get('pool', 'ANY'),
            )
```
Note that the second arg of the `get_contextual_dict()` call must match
the name of each `ContextualView` to evaluate in the upstream branch.

Also note that using a `ContextualView` as the Action Child has drawbacks in term of UX. We're waiting for a update of `kabaret` to fix this.

### Default Value

At the base of your context, you will probably want to have a set of default values.

You will do this by adding a 'get_default_contextual_edits()` method returning the default value.

Let's say your `Project` is the first level for you settings. You would
do something like:
```
class Project(flow.Object):

    settings = flow.Child(ContextualView)
    episodes = flow.Child(Episodes)

    def get_default_contextual_edits(self, context_name):
        if context_name == 'settings':
            return dict(
                fps=30,
                pool="ANY"
            )
```

## Special Case

Sometimes, you will want to put the visualisation/edition of the contextual values aside from the branch it affect.

An example would be the settings of a project. They affect the **WHOLE UNIVERSE** so maybe you wouldn't want them to show on the first page all users land to...

A classic aproach is to use an `admin` group and shove all geeky stuff in it:
```
Project
    word_of_the_day
    episodes
        ...
    admin
        settings
        config
        preferences
```

In this case, the `settings` object is not inside the `episodes` branch so it does not affect it. This is a fail at being usefull :/

To fix this, you can define inside `Project` a `get_contextual_view` method that returns a `ContextView` to consider as if it was its Child:
```
class Project(flow.Object):
    
    word_of_the_day = flow.Chid(WOTD)
    episodes = flow.Child(Episodes)
    admin = flow.Child(ProjectAdmin)

    def get_contextual_view(self, context_name):
        if context_name == 'settings':
            return self.admin.settings
        elif context_name == 'config'
            return self.admin.config

    def get_default_contextual_edits(self, context_name):
        if context_name == 'settings':
            return dict(
                fps=30,
                pool="ANY"
            )
```

**Note** that the default value must still be provided by the `Project` class !
            

Raw data

            {
    "_id": null,
    "home_page": "https://gitlab.com/kabaretstudio/kabaret.flow_contextual_dict",
    "name": "kabaret.flow-contextual-dict",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*",
    "maintainer_email": "",
    "keywords": "vfx animation pipeline asset library",
    "author": "Damien \"dee\" Coureau",
    "author_email": "kabaret-dev@googlegroups.com",
    "download_url": "https://files.pythonhosted.org/packages/cc/71/5a194d51ff21b12a9e22049e02cea1029c2052637c991fc788330ccf7858/kabaret.flow_contextual_dict-0.1.2.tar.gz",
    "platform": "",
    "description": "# kabaret.flow_contextual_dict\n\nThis package provide the `ContextualView` class and the `get_contextual_dict` function.\n\nTogether, they give your flow users the ability to use defined value\nanywhere in the branch underneeth and override those values where you \nsee fit in the branches.\n\nEverything is explained here, but if your of the kind that prefers to read and execute code, there is a demo flow in the package for that. Install the package an create a new project with the type `kabaret.flow_contextual_dict.demo_flow.DemoFlow`.\n\n## Concept\n\nHere is a quick example with this classic structure where `settings` are `ContextualView` Objects:\n```\nProject\n    settings\n    episodes\n        ep001\n            settings\n            sequences\n                seq001\n                    settings\n                    shots\n                        shot001\n                            settings\n                            anim\n                                settings\n                                init_action\n                                bake_action\n                            lighting\n                                settings\n                                init_action\n                                render_action\n                            comp\n                                settings\n                                init_action\n                                render_action\n                        shot002\n                seq002\n                    ...\n        ep002\n            ...\n```\nLet's say in the `Project.settings` defines `fps=24` and a `pool=\"ANY\"`.\nEvery object in the episodes branch can call `get_contextual_dict()` to receive a dict like `{fps:24, pool:\"ANY\"}`.\nMost likely, action of every step/department of every shot will use this.\n\nNow let's say the sequence `seq002` is in a hurry and you want to dispatch all actions on your farm's \"SUPER_COMPUTERS\" pool. All you need is to \"override\" with `pool=\"SUPER_COMPUTERS\"` in `ep002.settings`.\n\nYou can do this in each `settings` in the flow, and you can also \"add\" values in each of them (those \"overrides\" and \"adds\" are called \"edits\").\n\nIn a nutshell, it's a cascading dict, or as some call it: a **contextual dict**.\n\n## Install\n\n`pip install kabaret.flow_contextual_dict`\n\nPlease use a virtual env, it is good for you and your karma ^^\n\n## Usage\n\n### Defining Contexts\n\nIn order to add a contextual dict in your flow, you just need to add\na Child relation to a `ContextualView`:\n```\nclass Shot(flow.Object):\n\n    settings = flow.Child(contextualView)\n    ...\n\n```\n\nThe name of the relation is very important:\n- Overrides stacking is based on this name so you need to use the same\nname along your branch in order for overrides to work as expected.\n- It defines the \"context_name\" argument to use for `get_contextual_dict()` calls.\n\nSo this will not work:\n```\nProject\n    settings\n    episodes\n        ep001\n            episode_settings\n```\nBut this will:\n```\nProject \n    settings\n    episodes\n        ep001\n            settings\n```\nNote that you can use `Child().ui(label=\"Episode Settings\")` if you *really* want to display a different name in the GUI.\n\nThis gives the ability to use several contexts in the same flow.\nIn this structure, all * marked item are `ContextualView`. There is two\ncontext defined: `settings` and `config`. The first one drives values by `sequences` and `shots`, the second one only affects `episodes`.\n```\nProject\n    settings *\n    config *\n    episodes\n        ep001\n        config *\n        sequences\n            seq001\n                settings *\n                shots\n                    shot001\n                        settings *\n```\n\n### Editing Context Values\n\nOnce your flow is salted with `ContextualView`, the user will be able to\nadd value using the *\"Add\"* action and to edit values by double clicking on them.\n\nIf you want, for debug or inquiry, you can inspect the edits done thru a `ContectualView` by using its \"Show Edits\" actions. It will bring you to\na page showing only values defined here. Double-clicking one of those items\nwill show you more information, especially **the history of modification** for this value (what changed, who did it, and when).\nYou will also be able to change the override value, as well as disable/enable it.\n\nYou can also programatically edit the context by defining `get_default_contextual_edits(context_name)` methods returning a dict of value to use if no override exists for them.\n\nIn other words: user edits made with `ContextualView` actions will override values returned by a local or upstream `get_default_contextual_edits()` method.\n\n### Using Context Values\n\nIn order to get a context dict, you just need to call `get_contextual_dict(leaf, context_name)`. The `leaf` is the point in the branch where you want the value to be evaluated. It will most of the time be `self`. \n\nHere is an example in an Action.run():\n```\nclass SubmitRender(flow.Action):\n\n    render_settings = flow.Child(ContextualView)\n\n    def run(self, button):\n        if button == 'Confirm':\n            context = get_contextual_dict(\n                self, 'render_settings'\n            )\n            my_dispatcher.submit(\n                scene=self.get_scene_path(),\n                fps=context.get('fps', 24),\n                pool=context.get('pool', 'ANY'),\n            )\n```\nNote that the second arg of the `get_contextual_dict()` call must match\nthe name of each `ContextualView` to evaluate in the upstream branch.\n\nAlso note that using a `ContextualView` as the Action Child has drawbacks in term of UX. We're waiting for a update of `kabaret` to fix this.\n\n### Default Value\n\nAt the base of your context, you will probably want to have a set of default values.\n\nYou will do this by adding a 'get_default_contextual_edits()` method returning the default value.\n\nLet's say your `Project` is the first level for you settings. You would\ndo something like:\n```\nclass Project(flow.Object):\n\n    settings = flow.Child(ContextualView)\n    episodes = flow.Child(Episodes)\n\n    def get_default_contextual_edits(self, context_name):\n        if context_name == 'settings':\n            return dict(\n                fps=30,\n                pool=\"ANY\"\n            )\n```\n\n## Special Case\n\nSometimes, you will want to put the visualisation/edition of the contextual values aside from the branch it affect.\n\nAn example would be the settings of a project. They affect the **WHOLE UNIVERSE** so maybe you wouldn't want them to show on the first page all users land to...\n\nA classic aproach is to use an `admin` group and shove all geeky stuff in it:\n```\nProject\n    word_of_the_day\n    episodes\n        ...\n    admin\n        settings\n        config\n        preferences\n```\n\nIn this case, the `settings` object is not inside the `episodes` branch so it does not affect it. This is a fail at being usefull :/\n\nTo fix this, you can define inside `Project` a `get_contextual_view` method that returns a `ContextView` to consider as if it was its Child:\n```\nclass Project(flow.Object):\n    \n    word_of_the_day = flow.Chid(WOTD)\n    episodes = flow.Child(Episodes)\n    admin = flow.Child(ProjectAdmin)\n\n    def get_contextual_view(self, context_name):\n        if context_name == 'settings':\n            return self.admin.settings\n        elif context_name == 'config'\n            return self.admin.config\n\n    def get_default_contextual_edits(self, context_name):\n        if context_name == 'settings':\n            return dict(\n                fps=30,\n                pool=\"ANY\"\n            )\n```\n\n**Note** that the default value must still be provided by the `Project` class !",
    "bugtrack_url": null,
    "license": "LGPLv3+",
    "summary": "kabaret.flow contextual dict",
    "version": "0.1.2",
    "project_urls": {
        "Homepage": "https://gitlab.com/kabaretstudio/kabaret.flow_contextual_dict"
    },
    "split_keywords": [
        "vfx",
        "animation",
        "pipeline",
        "asset",
        "library"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "cc715a194d51ff21b12a9e22049e02cea1029c2052637c991fc788330ccf7858",
                "md5": "ca1abdbf6352bae34c5b3592b4e98815",
                "sha256": "cc0cffb5b647d0e3ad7fbe3c3fb912f7dfc052460459a13777d6f0ac745a8ef1"
            },
            "downloads": -1,
            "filename": "kabaret.flow_contextual_dict-0.1.2.tar.gz",
            "has_sig": false,
            "md5_digest": "ca1abdbf6352bae34c5b3592b4e98815",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*",
            "size": 27961,
            "upload_time": "2020-11-04T14:47:18",
            "upload_time_iso_8601": "2020-11-04T14:47:18.319579Z",
            "url": "https://files.pythonhosted.org/packages/cc/71/5a194d51ff21b12a9e22049e02cea1029c2052637c991fc788330ccf7858/kabaret.flow_contextual_dict-0.1.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2020-11-04 14:47:18",
    "github": false,
    "gitlab": true,
    "bitbucket": false,
    "codeberg": false,
    "gitlab_user": "kabaretstudio",
    "gitlab_project": "kabaret.flow_contextual_dict",
    "lcname": "kabaret.flow-contextual-dict"
}
        
Elapsed time: 0.18158s