Usage
Quickstart
General process
For a configured pattern, eg:
/mnt/prods/{prod}/shots/{seq}Given a path, eg:
/mnt/prods/hamlet/shots/sq010Resolva will extract and return this:
{"prod": "hamlet", "seq": "sq010"}
Simple complete usage example
Configuration:
from resolva import Resolver
template = {"maya_file": "/mnt/prods/{prod}/shots/{seq}/{shot}_{version:(v\d\d\d)}.{ext:(ma|mb)}",
"hou_file": "/mnt/prods/{prod}/shots/{seq}/{shot}_{version:(v\d\d\d)}.{ext:(hip|hipnc)}"}
Resolver("id", template) # create the Resolver in an instance cache
Resolving:
from resolva import Resolver
r = Resolver.get("id") # read the Resolver from the instance cache
input = "/mnt/prods/hamlet/shots/sq010/sh010_v012.ma"
label, data = r.resolve_first(input)
# result:
print(f'Detected type "{label}" and extracted "{data}"')
Output:
Detected type "maya_file" and extracted
{"prod": "hamlet", "seq": "sq010", "shot": "sh010", "version": "v012", "ext": "ma"}
Configuration
Pattern syntax
Instead of using regex, the pattern syntax is simplified and resembles the string format syntax.
Pattern example:
/mnt/prods/{prod}/shots/{seq}/{shot}_{version:(v\d\d\d)}.{ext:(ma|mb)}
Syntax notes:
pattern “keys” are between braces:
/mnt/prods/{prod}required values can optionally be set after a colon, for example:
a choice (“ma” or “mb”):
{ext:(ma|mb)}a pattern (“v” followed by 3 digits):
{version:(v\d\d\d)}a plain value (“asset”):
{type:asset}
Patterns dictionary
When resolving, we usually need to check multiple patterns, until one matches.
Thus, the configuration is a sorted dictionary containing multiple label: pattern mappings.
The pattern order is important. The most precise pattern should come before a more generic one, so the resolver hits it first.
Patterns dictionary example:
patterns = {"maya_file": r"/mnt/prods/{prod}/shots/{seq}/{shot}_{version:(v\d\d\d)}.{ext:(ma|mb)}",
"any_file": r"/mnt/prods/{prod}/shots/{seq}/{shot}_{version:(v\d\d\d)}.{ext}",
"sequence": "/mnt/prods/{prod}/shots/{seq}",
"project": "/mnt/prods/{prod}" }
In this example, the narrower maya_file pattern comes before the generic any_file.
Since a maya file is also a generic file, we want the maya_file pattern to be matched before any_file.
Pattern options
There are 3 advanced pattern options:
duplicate placeholders
anchor_start
anchor_end
These options are arguments of the Resolver instantiation. Please refer to the API.
Duplicate placeholders
If a pattern contains a placeholder twice, the resolver checks if the values are equal.
Example:
In this example shot appears twice:
/mnt/prods/{prod}/shots/{seq}/{shot}/{shot}_{version}.{ext}
The following input will raise a ResolvaException:
/mnt/prods/hamlet/shots/sq010/sh010/010_v001.ma because sh010 and 010 both match shot but are not equal.
Resolving and formatting
Creating the Resolver object
When the resolva.Resolver is instantiated, it is stored in cache.
This is done to keep the compiled regex from the configuration patterns in memory, for faster response.
We create the instance using a unique key, and pass the configuration. The key enables to create multiple Resolver instances per application, if needed.
The key can be of any type that is usable as dictionary key (must be hashable).
Example:
import resolva
patterns = {"maya_file": r"/mnt/prods/{prod}/shots/{seq}/{shot}_{version:(v\d\d\d)}.{ext:(ma|mb)}",
"any_file": r"/mnt/prods/{prod}/shots/{seq}/{shot}_{version:(v\d\d\d)}.{ext}",
"sequence": "/mnt/prods/{prod}/shots/{seq}",
"project": "/mnt/prods/{prod}" }
resolva.Resolver("any_id", patterns) # The instance is not used in the current code.
Getting the Resolver object
Once the Resolver was instantiated, it is in cache.
We retrieve it using the get(id: Any) factory.
Example:
import resolva
r = resolva.Resolver.get("any_id")
Now r holds the Resolver object.
Resolving
The Resolver has 3 resolve methods:
resolve_first
resolve_one
resolve_all
resolve_first
resolve_first resolves using the first available match.
It receives a string to resolve. It runs over the list of patterns (internally over the list of re.Pattern) until the first match.
This match generates a data dictionary. The method returns a tuple with the matching pattern label and the resolved data dictionary.
Example: resolving Maya file path, finds “maya_file” pattern
import resolva
input = "/mnt/prods/hamlet/shots/sq010/sh010_v012.ma"
r = resolva.Resolver.get("any_id")
label, data = r.resolve_first(input)
Result:
label:
maya_filedata:
{'prod': 'hamlet', 'seq': 'sq010', 'shot': 'sh010', 'version': 'v012', 'ext': 'ma'}
Example: resolving Nuke file path, finds “any_file” pattern
import resolva
input = "/mnt/prods/hamlet/shots/sq010/sh010_v012.nk"
r = resolva.Resolver.get("any_id")
label, data = r.resolve_first(input)
Result:
label:
any_filedata:
{'prod': 'hamlet', 'seq': 'sq010', 'shot': 'sh010', 'version': 'v012', 'ext': 'nk'}
resolve_one
resolve_one resolves using the given pattern.
It receives a string to resolve and a pattern label to match against. The Resolver then tries to match the string with the designated pattern.
If the match happens, a data dictionary is generated and returned. If not, an empty dictionary is returned
Example: resolving Maya file path with given “maya_file” pattern
import resolva
input = "/mnt/prods/hamlet/shots/sq010/sh010_v012.ma"
r = resolva.Resolver.get("any_id")
data = r.resolve_one(input, "maya_file")
Result:
data:
{'prod': 'hamlet', 'seq': 'sq010', 'shot': 'sh010', 'version': 'v012', 'ext': 'ma'}
Example: resolving Maya file path with given “any_file” pattern
import resolva
input = "/mnt/prods/hamlet/shots/sq010/sh010_v012.ma"
r = resolva.Resolver.get("any_id")
data = r.resolve_one(input, "any_file")
Result:
data:
{'prod': 'hamlet', 'seq': 'sq010', 'shot': 'sh010', 'version': 'v012', 'ext': 'ma'}
Example: resolving Maya file path with given “sequence” pattern: not matching
import resolva
input = "/mnt/prods/hamlet/shots/sq010/sh010_v012.ma"
r = resolva.Resolver.get("any_id")
data = r.resolve_one(input, "sequence")
Result: not matching
data:
{}
resolve_all
resolve_all resolves all possible matches.
It receives a string to resolve. It runs over the list of patterns (internally over the list of re.Pattern).
Every match generates a data dictionary. The method returns a dictionary with
each key: the matching pattern label
each value: the resolved data dictionary.
If there is no match, an empty dictionary is returned.
Example: resolving Maya file path with all patterns
import resolva
input = "/mnt/prods/hamlet/shots/sq010/sh010_v012.ma"
r = resolva.Resolver.get("any_id")
found = r.resolve_all(input)
Result:
found:
{'any_file': {'ext': 'ma', 'prod': 'hamlet','seq': 'sq010', 'shot': 'sh010','version': 'v012'}, 'maya_file': {'ext': 'ma', 'prod': 'hamlet', 'seq': 'sq010','shot': 'sh010','version': 'v012'}}
Example: resolving Nuke file path with all patterns
import resolva
input = "/mnt/prods/hamlet/shots/sq010/sh010_v012.nk"
r = resolva.Resolver.get("any_id")
found = r.resolve_all(input)
Result:
found:
{'any_file': {'ext': 'nk', 'prod': 'hamlet', 'seq': 'sq010', 'shot': 'sh010', 'version': 'v012'}}
Example: resolving non-matching string with all patterns
import resolva
r = resolva.Resolver.get("any_id")
found = r.resolve_all("blablabla")
Result:
found:
{}
Formatting
Formatting is the reverse of resolving. For a given string data dictionary, a formatted string is returned, according to the same configured patterns.
The Resolver has 3 format methods:
format_first
format_one
format_all
format_first
format_first formats using the first matching pattern.
It receives a string data dictionary to format. It runs over the list of patterns (internally over the internal “formats” dict) until the first match.
A match means:
the keys of the data dictionary match the keys of the patterns “format” string,
the formatted string resolves back to an identical data dictionary.
Once a match is found, a formatted string is generated and returned. The method returns a tuple with the label and the formatted string. Or a (None, None) tuple if there is no match.
Example: formatting Maya file dict with first matching pattern
import resolva
r = resolva.Resolver.get("any_id")
data = { 'prod': 'hamlet', 'seq': 'sq010', 'shot': 'sh010', 'version': 'v012', 'ext': 'ma'}
formatted = r.format_first(data)
Result:
formatted:
('maya_file', '/mnt/prods/hamlet/shots/sq010/sh010_v012.ma')
Example: formatting Sequence dict with first matching pattern
import resolva
r = resolva.Resolver.get("any_id")
data = {'prod': 'hamlet', 'seq': 'sq010'}
formatted = r.format_first(data)
Result:
formatted:
('sequence', '/mnt/prods/hamlet/shots/sq010')
format_one
format_one formats using the given pattern.
It receives a string data dictionary to format, and a pattern label to match against.
The Resolver then tries to match with the designated pattern. A match means:
the keys of the data dictionary match the keys of the patterns “format” string,
the formatted string resolves back to an identical data dictionary.
If the pattern matches, the generated formatted string is returned. Else, None is returned.
Example: formatting Sequence dict with given “sequence” pattern
import resolva
r = resolva.Resolver.get("any_id")
data = {'prod': 'hamlet', 'seq': 'sq010'}
formatted = r.format_one(data, "sequence")
Result:
formatted:
'/mnt/prods/hamlet/shots/sq010'
Example: formatting Sequence dict with given “project” pattern: not matching
import resolva
r = resolva.Resolver.get("any_id")
data = {'prod': 'hamlet', 'seq': 'sq010'}
formatted = r.format_one(data, "project")
Result:
formatted:
None
format_all
format_all formats using all possible matches.
It receives a string data dictionary to format. It runs over the list of patterns (internally over the internal “formats” dict).
Every match generates a formatted string.
A match means:
the keys of the data dictionary match the keys of the patterns “format” string,
the formatted string resolves back to an identical data dictionary.
The method returns a dictionary with all matching pattern labels as keys, and the formatted strings as values. If there is no match, an empty dictionary is returned.
Example: formatting Sequence dict with all patterns
import resolva
r = resolva.Resolver.get("any_id")
data = {'prod': 'hamlet', 'seq': 'sq010'}
formatted = r.format_all(data)
Result:
formatted:
{'sequence': '/mnt/prods/hamlet/shots/sq010'}
Example: formatting Maya file dict with all patterns
import resolva
r = resolva.Resolver.get("any_id")
data = { 'prod': 'hamlet', 'seq': 'sq010', 'shot': 'sh010', 'version': 'v012', 'ext': 'ma'}
formatted = r.format_all(data)
Result:
formatted:
{'maya_file': '/mnt/prods/hamlet/shots/sq010/sh010_v012.ma', 'any_file': '/mnt/prods/hamlet/shots/sq010/sh010_v012.ma'}
Control and introspection
The resolva.Resolver class has some extra methods to control and introspect its content.
These methods should not be useful for normal configuring, resolving and formatting.
For more details, please check out the API section.
Methods list:
get_id
get_labels
get_patterns
get_pattern_for
get_regexes
get_regex_for
get_formats
get_format_for
get_keys
get_keys_for