-
Notifications
You must be signed in to change notification settings - Fork 49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
More flexible templates #371
More flexible templates #371
Conversation
avalon/pipeline.py
Outdated
if os.path.isdir(pathdir): | ||
output = path | ||
|
||
# format representation template with context if 'path' wasn't a success |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
line too long (80 > 79 characters)
avalon/pipeline.py
Outdated
@@ -967,6 +956,9 @@ def update_current_task(task=None, asset=None, app=None): | |||
_session = Session.copy() | |||
_session.update(changed) | |||
changed["AVALON_WORKDIR"] = _format_work_template(template, _session) | |||
changed['AVALON_HIERARCHY'] = os.path.sep.join( | |||
asset_document['data']['parents'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will break pipelines that don't have the parents
data, right? This should allow for backwards compatibility.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
true. we'll put a .get() there with default of empty string to make sure it always resolve to something.
avalon/pipeline.py
Outdated
@@ -1003,6 +995,7 @@ def _format_work_template(template, session=None): | |||
"root": registered_root(), | |||
"project": session["AVALON_PROJECT"], | |||
"silo": session["AVALON_SILO"], | |||
"hierarchy": session['AVALON_HIERARCHY'], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will this error out on pipelines who haven't set AVALON_HIERARCHY
yet?
- Should this be in the Session schema if it's required?
- What is this value and when would you set it? How would you compute it for any asset?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes I'd say that making is required in the schema is reasonable. however there is a caveat here. Because it hold multiple key in the path joined together with a path.sep, it will be quite hard to parse the opposite way. So for example what you are using in your colorbleed config (get context from path) will likely not work.
AVALON_HIERARCHY resolve to a list of parents joined by path.sep so for example If asset is in this hierarchy: project1/assets/characters/hero
, then the template would be `{project/{hierarchy}/{asset}.
hierarchy
= 'assets/characters`
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to be made optional, as per the comments.
avalon/pipeline.py
Outdated
"app": Session.get("AVALON_APP", ""), | ||
"task": Session.get("AVALON_TASK", "") | ||
}) | ||
output = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add in the docstring the order of which it resolves the paths in the simplest sense. That way one can easily figure it out without reading the lines of code. It seems to have 3 ways of getting the data and I think it would be good to keep that order and reasoning clear for anyone trying out the function without looking at the code implementation.,
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to have been addressed.
Just a note, not a direct comment on your code of implementation. More dynamic paths I think would be warmly welcomed when it doesn't complicate things too much - since it allows for more customization for a specific studio. We just need to ensure that the template we give and allow isn't something that would easily break and introduces issues for simple pipelines or newcomers. (E.g. just storing the full path in a multiple OS pipeline will tend to introduce issues.) |
very true. it's bothering me too. we should probably make the stored full path as that last resort if all else fails. |
Hey guys, should we merge this? |
avalon/pipeline.py
Outdated
@@ -1190,6 +1186,13 @@ def switch(container, representation): | |||
def get_representation_path(representation): | |||
"""Get filename from representation document | |||
|
|||
There are three ways of getting the path from representation which are tried |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
line too long (80 > 79 characters)
Now I believe we can. I've changed the order of resolution based on the comments and it is now.
If any is successful, the following won't be tried. 1 is the new way of getting all needed from representation, 2. is exactly the same as before and 3. is fallback to a full path potentially stored on the representation. I've also added this into the docstring. We're quite happy with this and have it deployed in multiple places now. |
Hi Mkolar, i having this error
|
@mkolar should we also use:
in _format_work_template for case when hierarchy is empty? |
yes this should be fixed. we didn't catch it before |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems solid, I'll take care of the remaining few comments now.
avalon/pipeline.py
Outdated
@@ -1003,6 +995,7 @@ def _format_work_template(template, session=None): | |||
"root": registered_root(), | |||
"project": session["AVALON_PROJECT"], | |||
"silo": session["AVALON_SILO"], | |||
"hierarchy": session['AVALON_HIERARCHY'], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to be made optional, as per the comments.
avalon/pipeline.py
Outdated
"app": Session.get("AVALON_APP", ""), | ||
"task": Session.get("AVALON_TASK", "") | ||
}) | ||
output = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to have been addressed.
avalon/pipeline.py
Outdated
"task": Session.get("AVALON_TASK", "") | ||
}) | ||
output = None | ||
try: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This try/except block is too broad. At the moment, if the first formatting fails, the second doesn't happen. Also that first if output is None:
is superflous, can we remove that?
…bitary_hierarchy_templates # Conflicts: # avalon/pipeline.py
Mentioning #417 here, as this is one of those features that are important but difficult to test. For a test to pass in each permutation of this functionality, we need:
In each case, we need both a database entry per pair, but also existing paths on the file-system, as these won't return anything unless the path actually exists; unsure of whether that's actually the responsibility of this function, but am not sure how else to "automatically" cycle through the options (or whether this is actually better suited for handling by tools that can visualise this). |
I made a mistake on this one, the paths returned currently are the directories, not filenames! :O Original Refactored Lines 1227 to 1229 in 9b89842
Fixing this now. |
PR relates to both #308 and #351
New Functionality
This PR allows Avalon to work with arbitrary hierarchies in the system. This is currently used in 2 places.
Filling work path when launching an app and in 'workfiles' app and getting the path of published representation during loading.
Implementation
Getting representation path
Instead of hardcoding what keys we allow to be used in the template and also which template has to be used for publishing (as it is currently), store all the information we need directly on the representation. Proposed solution uses three possibilities to get the path which we try in sequence until one is successful.
representation['data']['path']
directly. We assume this is pre-filled full path to the file. If the folder exists on the disk, we use thisrepresentation['data']['template']
and format it withrepresentation['context']
. During this process we make sure thatroot
from the context get's replaced with registered root in avalon to keep it dynamic.example of what representation can look like in the db then
Formatting work path
The issue here was allowing any hierarchy to be filled into the path without putting too many restriction at what keys (sequence, shot, episode etc) can be used. The solution is introducing concept of
AVALON_HIERARCHY
which get's constructed on the fly from newparents
data on the given asset.asset['data']['parents']
is expected to be a correctly ordered list of all the hierarchical parents of the asset. This list get's parsed and joined withos.path.sep
ending up as a simple string that can be used in the template as{hierarchy}
key.We've used this in production for a while now, but it needs to be tested for backwards compatibility of course. As far as we can tell, nothing should break on previous projects, but better safe than sorry.
We found this feature crucial as different studios can have some seriously different preferences on what their folder structure looks like :). The implementation itself of course is up for discussion. The priority of individual ways of getting the path from representation for example. I find storing the absolute path in data useful as it might later allow extra checks to happen.