Repository navigation
Expand file tree
/
Copy pathnotes.txt
More file actions
196 lines (124 loc) · 5.38 KB
/
Copy pathnotes.txt
File metadata and controls
196 lines (124 loc) · 5.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
Zone
Zone.meta_path -> List of extra custom `Finder`s.
Multiple context/view processors can be via decorators, e.g.:
@zone.context_processor
def something(sdflkjsdf):
pass
Zone.view(tags) -> get a View of all matching Stores.
If there isn't a Store which specifies all of the tags, make one,
and put it at the front of the chain.
# The runtime context/view API.
zone.context_processors
@zone.context_processor
def something(ctx):
pass
Can context processors be global, and/or apply down the chain?
It might be keen to have global shotgun adapters which turn shotgun entities
into `{type}:{id}` tokens. Maybe.
Zone.getters
@zone.property
def fooprop(zone, context):
return something
@fooprop.setter
def fooprop(zone, context, value):
Zone.setters
zone.define('important_fields', type=list, subtype=str, default=['something'])
zone.define('pre_create', type=list, subtype='callable')
zone.add_constraint(...)
zone.add_argument(...)
zone.add_specs(...)
Zone.definitions
res = zone.call_many('pre_create', entity)
- Context is resolved into a view, and the view is checked for data.
- The data is checked for the zone-descriptor protocol:
def __getzoneitem__(self, key, zone, view???):
pass
def __setzoneitem__(self, ...):
pass
We also have a decorator for that:
@zoneproperty
def something(view, view_tags):
# return something
@something.setter
def something(view, value, view_tags):
# set something
Contexts and Tags
=================
A "context" is a mapping of string keys to arbitrary types.
Context processors can manipulate the contents of that mapping, turning non-atomic
values into atomic ones.
The "tags" are a mapping of string keys to strings or ints.
HTTPFinder/HTTPLoader -> a Finder that is backed by an http server.
Assume Nginx `autoindex_format json`, and allow for `foo/bar.ext` and `foo.bar.ext`.
JSONSource
View -> a list of DataStore.
Proxy setting to the first store, and getting to the first store which responds.
- can load from many places:
- envvars
- files
- redis
- http (cached)
- dns (cached)
- those zones can have definitions for what is allowed (in a very argparse
or sgcache.config sort of way), or a callback to
intercept what is allowed, or allow anything
- Allowable types constrained to something we can YAML. Either the base config
or the consumer needs to declare something a callable, otherwise we can't
quite tell the different between string entrypoints and string values.
- int
- string literal
- string pattern (to be applied with .format in the resolved view)
- callable (or string entry_point)
- list of any of above
- dict of any of above
- magic values in the zones describe meta behaviour:
def __context_processor__(args):
# return some kwargs
- an import-protocol-like mechanism for you to add loaders
zoneconfig.meta_path is a list of finders/loaders
- when you get/set values, you can provide context args and kwargs.
Args must be turned into kwargs by the zones, and kwargs all may be
interpreted or rejected. Those kwargs may or may not be raw view tags. Any
whose values are not str or int will be silently dropped.
def __resolve_context__(zone, context_objs, view_tags):
# Turn context objects into view tags.
# Default does nothing.
for x in context_objs:
if isinstance(x, Entity):
view_tags.setdefault('sgsession:{}'.format(x.type), x.id)
def __load_views(zone, tags):
# Trigger the dynamic loaders to go looking for tags.
zone.load_views(tags)
def __view_chain__(zone, tags):
# Return a chain of matching views, ordered by their described "order"
# and then insertion order into the dict (cause it is an odict!)
return zone.view_chain(tags)
- context objects select a "view" of that zone, which has partial overrides
of the zone for that context. Different views may also have different
storage mechanisms and expiry times. E.g. a `zoneconfig:storage=user` could signal
that values stored here should go into `~/.config/zoneconfig/{zone}?{view}.yaml`
with zone.view(('sgsession:Project', 123)) as view:
view['launcher_default_version'] = '2018'
View.order:
- Where this view will land when resolved.
View.tokens:
- The dict of tokens that are evaluated against the context to determine
if this view applies.
- Keys must be strings, and values either strings or ints.
- A magic `('_op', 'any')` determines that any token must
match, where it defaults to `all` tokens must match.
- Deterministic serialization into a modified query syntax that preserves types:
`bar=s123&foo=i123&_op=any`
Views should be able to be dynamic as well, e.g. hitting Shotgun or HTTP
when requested.
- events/callbacks -> https://pyee.readthedocs.io/en/latest/
- sgtk/tank calls these sorts of things "hooks".
USE CASES
---------
- Default Maya version for studio/project.
- Fields that sgsession should call important/parents/etc.
- Fields that should be included in sgfs tags by default.
- List of Maya pre-publish and pre-save checks.
- sgactions actions for a given entity type or even entity.
- What mounts a computer mounts at boot. It provides it's IP as a context,
and the context processor can check it against various netmasks to get view names.