API

Resolver —

class resolva.Resolver[source]

Main class and entry point to use Resolva.

When a Resolver object is created, it is set in an instance cache (in memory), for faster usage later. The instance contains the compiled regex patterns, which do not need to be recompiled later.

Examples

>>> # 1. Reading the patterns and creating the Resolver instance
>>> 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}" }
>>> __ = Resolver("any_id", patterns)  # the instance is created and set in the cache
>>> # 2. Getting and using the instance
>>> r = Resolver.get("any_id")
>>> print(r)
[resolva.Resolver] ID: [any_id] - Pattern labels: ['maya_file', 'any_file', 'sequence', 'project']
>>> # Can also be done in one call
>>> r = Resolver.get("other_id") or Resolver("other_id", patterns)  # getting from instance cache, or creating object
>>> print(r)
[resolva.Resolver] ID: [other_id] - Pattern labels: ['maya_file', 'any_file', 'sequence', 'project']

The Resolver object holds all methods to use the resolver, for resolving and formatting.

__init__(id, patterns, check_duplicate_placeholders=True, anchor_start=True, anchor_end=True)[source]

Creates a Resolver instance.

The expected “patterns” is a dictionary holding pattern templates. - Each key is a “label”: any string to identify the pattern. - Each value is a “pattern”: a pattern string

On instantiation, each pattern in the “patterns” dictionary is translated into regex and compiled to re.Pattern objects. This results in an internal “regexes” dictionary.

Also, each pattern in the “patterns” dictionary is translated into a “format” string. This string is used to apply the format function, for the Resolvers formatting feature. All “format” strings are stored in an internal “formats” dict, with labels as keys.

Each pattern is a string containing keywords, in curly brackets, eg “{project}”, that will be matched by the Resolver. These keywords are stored in an internal “keys” dictionary, with labels as dict keys, and a set of keywords as value.

The last arguments are configuration options.

>>> 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}" }
>>> r = Resolver("any_id", patterns)
>>> print(r)
[resolva.Resolver] ID: [any_id] - Pattern labels: ['maya_file', 'any_file', 'sequence', 'project']
Parameters:
  • id (str) – Any value that can be used as a dictionary key, to store the Resolver instance

  • patterns (dict[str, str]) – The {label: pattern} dictionary

  • check_duplicate_placeholders (bool) – if the pattern may contain duplicate placeholders, and if the Resolver should check if their resolved values are identical.

  • anchor_start (bool) – if each patterns starts with regex “^”

  • anchor_end (bool) – if each patterns ends with regex “$”

static get(id)[source]

Static factory method to retrieve an existing Resolver object from the instance cache. The given id should be an id already used during Resolver creation.

Example

>>> # the instance was created in earlier example
>>> r = Resolver.get("any_id")
>>> print(r)
[resolva.Resolver] ID: [any_id] - Pattern labels: ['maya_file', 'any_file', 'sequence', 'project']
Parameters:

id (Any) – the id that was previously used during instantiation of the Resolver

Returns:

A resolver instance

Return type:

Resolver | None

get_id()[source]

Gets the id for the current Resolver instance.

Example

>>> # the instance was created in earlier example
>>> r = Resolver.get("any_id")
>>> print(r.get_id())
any_id
Returns:

the id that was used during instantiation of the Resolver

Return type:

Any

get_labels()[source]

Returns the list of pattern labels, as set during instantiation of the Resolver

Example

>>> # the instance was created in earlier example
>>> r = Resolver.get("any_id")
>>> print(r.get_labels())
['maya_file', 'any_file', 'sequence', 'project']
Returns:

List of pattern labels

Return type:

list[str]

get_patterns()[source]

Returns the patterns dictionary, as set during instantiation of the Resolver

Example

>>> # the instance was created in earlier example
>>> from pprint import pprint
>>> r = Resolver.get("any_id")
>>> pprint(r.get_patterns(), sort_dicts=True)
{'any_file': '/mnt/prods/{prod}/shots/{seq}/{shot}_{version:(v\\d\\d\\d)}.{ext}',
 'maya_file': '/mnt/prods/{prod}/shots/{seq}/{shot}_{version:(v\\d\\d\\d)}.{ext:(ma|mb)}',
 'project': '/mnt/prods/{prod}',
 'sequence': '/mnt/prods/{prod}/shots/{seq}'}
Returns:

The patterns dictionary

Return type:

dict[str, str]

get_pattern_for(label)[source]

Returns the pattern for the given label. As stored in the patterns dictionary set during instantiation of the Resolver

Example

>>> # the instance was created in earlier example
>>> r = Resolver.get("any_id")
>>> print(r.get_pattern_for("sequence"))
/mnt/prods/{prod}/shots/{seq}
Parameters:

label (str) – a pattern label, must exist as key in the patterns dictionary

Returns:

The pattern stored in the patterns dictionary for the given label key.

Return type:

str | None

get_regexes()[source]

On instantiation of the resolver, each pattern in the “patterns” dictionary is translated into regex, and compiled to re.Pattern objects.

This results in an internal “regexes” dictionary: - Each key is a “label”: string used to identify the pattern. - Each value is a “regex”: a compiled regex object, generated from the corresponding “pattern”.

This function is useful for controlling and debugging. Is it not necessary to manipulate the regexes to resolve or format.

Example

>>> # the instance was created in earlier example
>>> from pprint import pprint
>>> r = Resolver.get("any_id")
>>> pprint(r.get_regexes(), sort_dicts=True)
{'any_file': re.compile('^/mnt/prods/(?P<prod001>[^/]*)/shots/(?P<seq001>[^/]*)/(?P<shot001>[^/]*)_(?P<version001>(v\\d\\d\\d)).(?P<ext001>[^/]*)$'),
 'maya_file': re.compile('^/mnt/prods/(?P<prod001>[^/]*)/shots/(?P<seq001>[^/]*)/(?P<shot001>[^/]*)_(?P<version001>(v\\d\\d\\d)).(?P<ext001>(ma|mb))$'),
 'project': re.compile('^/mnt/prods/(?P<prod001>[^/]*)$'),
 'sequence': re.compile('^/mnt/prods/(?P<prod001>[^/]*)/shots/(?P<seq001>[^/]*)$')}
Returns:

The internal compiled regexes dictionary resulting from the patterns.

Return type:

dict[str, re.Pattern]

get_regex_for(label)[source]

Returns the compiled regex expression for the given label. As stored in the internal regexes dictionary

Example

>>> # the instance was created in earlier example
>>> r = Resolver.get("any_id")
>>> print(r.get_regex_for("sequence"))
re.compile('^/mnt/prods/(?P<prod001>[^/]*)/shots/(?P<seq001>[^/]*)$')
Parameters:

label (str) – a pattern label, must exist as key in the patterns dictionary

Returns:

The regex stored in the regexes dictionary for the given label key.

Return type:

re.Pattern | None

get_formats()[source]

Each pattern in the “patterns” dictionary is translated into a “format” string. This string is used to apply the format function, for the Resolvers formatting feature. All “format” strings are stored in an internal “formats” dict, with labels as keys.

Example

>>> # the instance was created in earlier example
>>> r = Resolver.get("any_id")
>>> print(r.get_formats())
{'maya_file': '/mnt/prods/{prod}/shots/{seq}/{shot}_{version}.{ext}', 'any_file': '/mnt/prods/{prod}/shots/{seq}/{shot}_{version}.{ext}', 'sequence': '/mnt/prods/{prod}/shots/{seq}', 'project': '/mnt/prods/{prod}'}
Returns:

The internal formats dictionary, resulting from the patterns.

Return type:

dict[str, str]

get_format_for(label)[source]

Returns the format string for the given label. As stored in the internal “formats” dictionary.

Example

>>> # the instance was created in earlier example
>>> r = Resolver.get("any_id")
>>> print(r.get_format_for("sequence"))
/mnt/prods/{prod}/shots/{seq}
Parameters:

label (str) – a pattern label, must exist as key in the patterns dictionary

Returns:

The string stored in the “formats” dictionary for the given label key.

Return type:

str | None

get_keys()[source]

Each pattern is a string containing keywords, in curly brackets, eg “{project}”, that will be matched by the Resolver. These keywords are stored in an internal “keys” dictionary, with labels as dict keys, and a set of keywords as value.

Example

>>> # the instance was created in earlier example
>>> r = Resolver.get("any_id")
>>> for k, v in r.get_keys().items():                     print(f"{k} => {sorted(v)}")
maya_file => ['ext', 'prod', 'seq', 'shot', 'version']
any_file => ['ext', 'prod', 'seq', 'shot', 'version']
sequence => ['prod', 'seq']
project => ['prod']
Returns:

The internal “keys” dictionary

Return type:

dict[str, set]

get_keys_for(label)[source]

Returns the set of keywords for the given label. As stored in the internal “keys” dictionary.

Example

>>> # the instance was created in earlier example
>>> r = Resolver.get("any_id")
>>> print(r.get_keys_for("project"))
{'prod'}
Parameters:

label (str) – a pattern label, must exist as key in the patterns dictionary

Returns:

The set of keywords stored in the “keys” dictionary for the given label.

Return type:

set | None

resolve_first(string)[source]

The Resolver has 3 resolve methods: - resolve_first - resolve_one - resolve_all

This 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.

Examples

>>> input = "/mnt/prods/hamlet/shots/sq010/sh010_v012.ma"
>>> r = Resolver.get("any_id")
>>> label, data = r.resolve_first(input)
>>> print(f'Label: "{label}" - Data: "{data}"')
Label: "maya_file" - Data: "{'prod': 'hamlet', 'seq': 'sq010', 'shot': 'sh010', 'version': 'v012', 'ext': 'ma'}"
>>> input = "/mnt/prods/hamlet/shots/sq010/sh010_v012.nk"
>>> r = Resolver.get("any_id")
>>> label, data = r.resolve_first(input)
>>> print(f'Label: "{label}" - Data: "{data}"')
Label: "any_file" - Data: "{'prod': 'hamlet', 'seq': 'sq010', 'shot': 'sh010', 'version': 'v012', 'ext': 'nk'}"
Parameters:

string (str) – a string to resolve, typically a path

Returns:

Tuple with the first matching pattern label and the resolved data dictionary

Return type:

tuple[str, dict[str, str]] | tuple[(None, None)]

resolve_one(string, label)[source]

The Resolver has 3 resolve methods: - resolve_first - resolve_one - resolve_all

This resolve_one resolves using the designated 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

Examples

>>> input = "/mnt/prods/hamlet/shots/sq010/sh010_v012.ma"
>>> r = Resolver.get("any_id")
>>> data = r.resolve_one(input, "maya_file")
>>> print(data)
{'prod': 'hamlet', 'seq': 'sq010', 'shot': 'sh010', 'version': 'v012', 'ext': 'ma'}
>>> input = "/mnt/prods/hamlet/shots/sq010/sh010_v012.ma"
>>> r = Resolver.get("any_id")
>>> data = r.resolve_one(input, "any_file")
>>> print(data)
{'prod': 'hamlet', 'seq': 'sq010', 'shot': 'sh010', 'version': 'v012', 'ext': 'ma'}
>>> data = r.resolve_one(input, "sequence")
>>> print(data)
{}
Parameters:
  • string (str) – a string to resolve, typically a path, and the label of a pattern to match against

  • label (str) –

Returns:

Resolved data dictionary or empty dictionary if there is no match.

Return type:

dict[str, str] | dict

resolve_all(string)[source]

The Resolver has 3 resolve methods: - resolve_first - resolve_one - resolve_all

This 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.

Examples

>>> from pprint import pprint
>>> input = "/mnt/prods/hamlet/shots/sq010/sh010_v012.ma"
>>> r = Resolver.get("any_id")
>>> found = r.resolve_all(input)
>>> pprint(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'}}
>>> input = "/mnt/prods/hamlet/shots/sq010/sh010_v012.nk"
>>> found = r.resolve_all(input)
>>> pprint(found)
{'any_file': {'ext': 'nk',
              'prod': 'hamlet',
              'seq': 'sq010',
              'shot': 'sh010',
              'version': 'v012'}}
>>> found = r.resolve_all("blablabla")
>>> print(found)
{}
Parameters:

string (str) – a string to resolve, typically a path

Returns:

Dictionary with all matching pattern labels as keys, and the resolved data dictionaries as values. An empty dictionary if there is no match.

Return type:

dict[str, dict[str, str]] | dict

format_first(data)[source]

The Resolver has 3 format methods: - format_first - format_one - format_all

This 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 matches 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.

Examples

>>> r = Resolver.get("any_id")
>>> data = { 'prod': 'hamlet', 'seq': 'sq010', 'shot': 'sh010', 'version': 'v012', 'ext': 'ma'}
>>> formatted = r.format_first(data)
>>> print(formatted)
('maya_file', '/mnt/prods/hamlet/shots/sq010/sh010_v012.ma')
>>> data = {'prod': 'hamlet', 'seq': 'sq010'}
>>> formatted = r.format_first(data)
>>> print(formatted)
('sequence', '/mnt/prods/hamlet/shots/sq010')
Parameters:

data (dict[str, str]) – a string data dictionary to format

Returns:

a tuple with the label and the formatted string, or (None, None) if there is no match.

Return type:

tuple[str, str] | tuple[(None, None)]

format_one(data, label)[source]

The Resolver has 3 format methods: - format_first - format_one - format_all

This format_one formats using the designated 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 matches 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.

Examples

>>> data = {'prod': 'hamlet', 'seq': 'sq010'}
>>> r = Resolver.get("any_id")
>>> formatted = r.format_one(data, "sequence")
>>> print(formatted)
/mnt/prods/hamlet/shots/sq010
>>> formatted = r.format_one(data, "project")
>>> print(formatted)
None
Parameters:
  • data (dict[str, str]) – a string data dictionary to format

  • label (str) –

Returns:

the formatted string, or None if the pattern does not match.

Return type:

str | None

format_all(data)[source]

The Resolver has 3 format methods: - format_first - format_one - format_all

This 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 matches 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.

Examples

>>> data = {'prod': 'hamlet', 'seq': 'sq010'}
>>> r = Resolver.get("any_id")
>>> formatted = r.format_all(data)
>>> print(formatted)
{'sequence': '/mnt/prods/hamlet/shots/sq010'}
>>> data = { 'prod': 'hamlet', 'seq': 'sq010', 'shot': 'sh010', 'version': 'v012', 'ext': 'ma'}
>>> r = Resolver.get("any_id")
>>> formatted = r.format_all(data)
>>> print(formatted)
{'maya_file': '/mnt/prods/hamlet/shots/sq010/sh010_v012.ma', 'any_file': '/mnt/prods/hamlet/shots/sq010/sh010_v012.ma'}
Parameters:

data (dict[str, str]) – a string data dictionary to format

Returns:

Dictionary with all matching pattern labels as keys, and the formatted strings as values. An empty dictionary if there is no match.

Return type:

dict[str, dict[str, str]] | dict