ways.api module

Expose common functionality.

This module’s responsibility to maintain backwards and forwards compatibility so that this package can be refactored without breaking any tools.

It’s recommended to always import and use modules, here.

ways.api.decode(obj)[source]

dict[str]: Convert a URL-encoded string back into a dict.

ways.api.encode(obj)[source]

Make the given descriptor information into a standard URL encoding.

Parameters:
  • obj (dict[str]) – The Descriptor information to serialize.
  • is normally something like (This) –
  • {'create_using' – ways.api.FolderDescriptor}.
Returns:

The output encoding.

Return type:

str

class ways.api.Plugin[source]

Bases: object

An add-on that is later retrieved by Context to gather its data.

add_to_registry = True
data

**dict[str]* – The display properties (like {‘color’* – ‘red’}).

class ways.api.DataPlugin(name, sources, info, assignment)[source]

Bases: ways.base.plugin.Plugin

An add-on that was made from a serialized file (JSON/YAML/etc).

This class behaves exactly like a regular Plugin object and is stored in the same space as Plugin objects.

DataPlugin does not add itself to the cache automatically. It is the responsibility of some other class/function to register it to Ways.

We do this so that we can have better control over the DataPlugin’s args and its assignment before it hits the cache.

add_to_registry = False
get_assignment()[source]

str: Where this Plugin lives in Ways, along with its hierarchy.

get_groups()[source]

Get the groups that this Plugin evaluates onto.

Note

The term ‘groups’ is not the same as the assignment of a Plugin. They are two different things.

Returns:The groups.
Return type:tuple[str]
get_hierarchy()[source]

tuple[str] or str: The location that this Plugin exists within.

get_mapping()[source]

str: The physical location of this Plugin (on the filesystem).

get_mapping_details()[source]

dict[str]: Information about the mapping, if needed.

get_max_folder()[source]

str: The furthest location up that this plugin can navigate to.

get_platforms()[source]

set[str]: The platforms that this Plugin is allowed to run on.

get_uses()[source]

tuple[str]: The Context hierarchies this instance depends on.

get_uuid()[source]

str: A unique ID for this plugin.

is_path()[source]

If the mapping is a filepath or None if unsure.

Returns:If the mapping is a path to a file/folder on disk.
Return type:bool or NoneType
class ways.api.Context(hierarchy, assignment='', connection=None)[source]

Bases: object

A collection of plugins that are read in order to resolve its methods.

as_dict(changes=True)[source]

Convert this object into a dictionary.

This is different from a standard repr(Context) because it will include items that are not part of the Context’s initialization.

It also creates a deepcopy of its contents, so that any changes to this dictionary won’t affect the original object.

Parameters:changes (bool, optional) – If True, the output will contain original plugin data as well as any changes that the user made over top of the original. If False, only the original information is returned. Default is True.
Returns:A copy of the current information of this class.
Return type:dict[str]
checkout(assignment='master')[source]

Make a new Context instance and return it, with the same hierarchy.

Parameters:assignment (str, optional) – The new assignment to get.
Returns:The new Context object.
Return type:ways.api.Context
data

dict[str] – Data that was automatically generated and user data.

get_action(name)[source]

ways.api.Action or callable or NoneType: The Action.

get_all_plugins(hierarchy='', assignment='')[source]

list[ways.api.Plugin]: The found plugins, if any.

get_all_tokens()[source]

Get the tokens in this Context’s mapping and any subtokens.

Subtokens are tokens that are inside another token’s mapping.

Returns:All of the tokens known to this Context.
Return type:set[str]
get_assignment()[source]

str: The assignment for this Context.

get_groups()[source]

tuple[str]: The groups that this Context belongs to.

get_hierarchy()[source]

tuple[str]: The path to this Context.

get_mapping()[source]

str: The mapping that describes this Context.

get_mapping_details()[source]

Get the information that describes a Context instance’s mapping.

This function is the same as “mapping_details” key that you’d see in a Plugin Sheet file and is critical to how a Context’s parser builds into a file path.

Without it, you cannot get a proper filepath out of a Context.

Returns:The information.
Return type:dict[str]
get_mapping_tokens(mapping='')[source]

list[str]: Get all of the tokens that are in this Context’s mapping.

get_max_folder()[source]

str: The highest mapping point that this Context lives in.

get_parser()[source]

ways.api.ContextParser: A parser copy that points to this Context.

get_platforms()[source]

Get The OSes that this Context runs on.

The recognized platforms for this method is anything that platform.system() would return. (Examples: [‘darwin’, ‘java’, ‘linux’, ‘windows’]).

Returns:The platforms that this Context is allowed to run on.
Return type:set[str]
get_str(*args, **kwargs)[source]

Get the Context’s mapping as filled-out text.

Parameters:
  • *args (list) – Positional args to send to ways.api.ContextParser.get_str.
  • **kwargs (dict) – Keyword args to send to ways.api.ContextParser.get_str.
is_path()[source]

bool: If the user indicated that the given mapping is a filepath.

plugins

Find all of the “valid” plugins for this instance.

What decides if a Plugin is “found” depends on a number of factors. First, the plugin needs to be inside the hierarchy of the Context, have the same assignment, and the platform(s) assigned to the Plugin must match our current system’s platform. If a platform override is specified (aka if WAYS_PLATFORM has been set) then the Plugin object’s platform has to match that, instead.

Raises:
  • ValueError – If the platform in WAYS_PLATFORM was invalid.
  • ValueError – If the plugin found has a platform that is not found in our recognized_platforms variable.
Returns:

The found plugins.

Return type:

list[ways.api.Plugin]

revert()[source]

Set the data on this instance back to its default.

classmethod validate_plugin(plugin)[source]

Check if a plugin is “valid” for this Context.

Typically, a plugin is invalid if it was meant for a different OS (example), a Windows plugin shouldn’t be added to a Context that is being run on a Linux machine.

Parameters:

plugin (ways.api.Plugin) – The plugin to check.

Raises:
  • OSError – If the user specified an unrecognized environment using the PLATFORM_ENV_VAR environment variable.
  • EnvironmentError – If the plugin’s environment does not match this environment.
Returns:

The plugin (completely unmodified).

Return type:

ways.api.Plugin

ways.api.get_context(hierarchy, assignment='', follow_alias=False, force=False, *args, **kwargs)[source]

Get a persistent Context at some hierarchy/assignment location.

This function uses a Flyweight factory to manage the instance objects that it returns.

Reference:
http://sourcemaking.com/design_patterns/flyweight http://sourcemaking.com/design_patterns/flyweight/python/1
Parameters:
  • hierarchy (tuple[str]) – The location to look for our instance.
  • assignment (str) – The category/grouping of the instance. If no assignment is given, Ways will gather plugins in the order defined in the WAYS_PRIORITY environment variable and create plugins based on that.
  • *args (list) – If an object instance is found at the hierarchy/assignment, this gets passed to the instantiation of that object.
  • **kwargs (dict[str]) – If an object instance is found at the hierarchy/assignment, this gets passed to the instantiation of that object.
Returns:

An instance of that class. If the Context that is queried doesn’t have any Plugin objects defined for it, it’s considered ‘empty’. To avoid faults in our code, we return None.

Return type:

<class_tuple instance> or NoneType

ways.api.register_context_alias(alias_hierarchy, old_hierarchy)[source]

Set a hierarchy to track the changes of another hierarchy.

This function lets you refer to plugins and Context objects without specifying their full names.

Example

>>> class SomePlugin(plugin.Plugin):
>>>     def get_mapping(self):
>>>         return '/some/path/here'
>>>     def get_hierarchy(self):
>>>         return ('nuke', 'scenes')
>>>     def get_platforms(self):
>>>         return '*'
>>> class AnotherPlugin(plugin.Plugin):
>>>     def get_mapping(self):
>>>         return '/some/path/here'
>>>     def get_hierarchy(self):
>>>         return ('maya', 'scenes')
>>>     def get_platforms(self):
>>>         return '*'
>>> sit.register_context_alias('maya_scenes', 'maya/scenes')
>>> context = ways.api.get_context('maya_scenes')
>>> # The resulting Context object has the hierarchy ('maya_scenes', )
>>> # but has all of the plugins from 'maya/scenes'
>>> sit.register_context_alias('maya_scenes', 'nuke/scenes')
>>> # Now, the Context('maya_scenes') is pointing to a Nuke Context
>>> # we can immediately work with this Context without having to
>>> # re-instantiate the Context
Raises:ValueError – If the alias is the same as the hierarchy that it’s trying to be aliased to or if the alias was already defined.
ways.api.resolve_alias(hierarchy)[source]

Get the real hierarchy that the given alias represents.

Parameters:hierarchy (iter[str] or str) – The alias hierarchy to convert.
Returns:The real hierarchy.
Return type:tuple[str]
ways.api.clear_aliases()[source]

Remove all the stored aliases in this instance.

ways.api.clear_contexts()[source]

Remove every Context instance that this object knows about.

If a Context is re-queried after this method is run, a new instance for the Context will be created and returned.

Running this method is not recommended because it messes with the internals of Ways.

class ways.api.Asset(info, context, parse_type='regex')[source]

Bases: object

An object that contains a Context and data about the Context.

The idea of this class is to keep Context information abstract, and let Context parse/use that information. Depending on what the Context is for, it could be used to ground the information to a filesystem or a database or some other structure that the Context knows about.

get_missing_required_tokens()[source]

Find any token that still needs to be filled for our parser.

If a token is missing but it has child tokens and all of the child tokens are defined, it is excluded from the final output. If the missing token is a child of some parent token that is defined, then the value of the token is parsed. If the parse is successful, the token is excluded from the final output.

Returns:Any tokens that have no value.
Return type:list[str]
get_str(required=True, *args, **kwargs)[source]

Get the full path to the asset, if any.

Parameters:
  • required (bool, optional) – If True and there are tokens that are required that still are not filled, raise an error. If False, return the incomplete string. Default is True.
  • *args (list) – Positional args to send to ContextParser.get_str.
  • **kwargs (list) – Keywords args to send to ContextParser.get_str.
Raises:

ValueError – If required is True (in other words, we assume that)

Returns:

The resolved string for this instance.

Return type:

str

get_token_parse(name, parse_type='')[source]

Get the parse expression for some token name.

Parameters:
  • name (str) – The name of the token to get parse details from.
  • parse_type (str, optional) – The engine type whose expression will be returned. If no parse_type is given, the stored parse_type is used.
Returns:

The parse expression used for the given token.

get_unfilled_tokens(required_only=False)[source]

Get the tokens in this instance that still don’t have values.

Parameters:required_only (bool, optional) – If True, do not return optional tokens. If False, return all tokens, required and optional. Default is False.
Returns:The tokens that still need values.
Return type:list[str]
get_value(name, real=False)[source]

Get some information about this asset, using a token-name.

If the information is directly available, we return it. If it isn’t though, it is searched for, using whatever information that we do have.

If the token name is a child of another token that is defined, we use the parent token to “build” a value for the token that was requested.

If the token name is a parent of some other tokens that all have values, we try to “build” it again, by combining all of the child tokens.

In both cases, the return value is created but not defined. But it lets you do this:

Example

>>> shot_info = {
...     'JOB': 'someJob',
...     'SCENE': 'SOMETHING',
...     'SHOT': 'sh0010'  # Pretend SHOT_NUMBER is a child of SHOT
... }
>>> shot_asset = resource.Asset(shot_info, context='job/scene/shot')
>>> shot_asset.get_value('SHOT_NUMBER')
... # Result: '0010'
Parameters:
  • name (str) – The token to get the value of.
  • real (bool, optional) – If True, the original parsed value is returned. If False and the given token has functions defined in “before_return” then those functions will process the output and then return it. Default is False.
Returns:

The value at the given token.

set_value(key, value, force=False)[source]

Store the given value to some key.

Parameters:
  • key (str) – The token that our value will be stored into.
  • value (str) – The value to store.
  • force (bool, optional) – If False, values are checked against their tokens before being set. If True, values are set for each token, even if they are not valid input for that token. Default is False.
ways.api.get_asset(info, context=None, *args, **kwargs)[source]

Get some class object that matches the given Context and wraps some info.

Parameters:
  • info (dict[str] or str) – The info to expand. If the input is a dict, it is passed through and returned. If it is a string, the string is parsed against the given context. Generally speaking, it’s better to give a string that is an exact or partial match to a Context’s mapping than it is to give a dict. This is doubly true if no context is given.
  • context (ways.api.Context or str or tuple[str]`, optional) – The Context to use for the asset. If a string is given, it is assumed to be the Context’s hierarchy and a Context object is constructed. If nothing is given, the best possible Context is “found” and tried. This auto-find process will try to find the “best” match by looking at every known Context’s mapping. A match is not guaranteed. Default is None.
  • *args (list) – Optional position variables to pass to our found class’s constructor.
  • **kwargs (dict) – Optional keyword variables to pass to our found class’s constructor.
Raises:

NotImplementedError – If context is None. There’s no auto-find-context option yet.

Returns:

The found class object or NoneType. If no class definition was found for the given Context, return a generic Asset object.

ways.api.get_asset_class(hierarchy)[source]

Get the class that is registered for a Context hierarchy.

ways.api.get_asset_info(hierarchy)[source]

Get the class and initialization function for a Context hierarchy.

Parameters:hierarchy (tuple[str] or str) – The hierarchy to get the asset information of.
Returns:The class type and the function that is used to instantiate it.
Return type:tuple[classobj, callable]
ways.api.register_asset_class(class_type, context, init=None, children=False)[source]

Change get_asset to return a different class, instead of an Asset.

The Asset class is useful but it may be too basic for some people’s purposes. If you have an existing class that you’d like to use with Ways,

Parameters:
  • class_type (classobj) – The new class to use, instead. context (str or ways.api.Context): The Context to apply our new class to.
  • init (callable, optional) – A function that will be used to create an instance of class_type. This variable is useful if you need to customize your class_type’s __init__ in a way that isn’t normal (A common example: If you want to create a class_type that does not pass context into its __init__, you can use this variable to catch and handle that).
  • children (bool, optional) – If True, this new class_type will be applied to child hierarchies as well as the given Context’s hierarchy. If False, it will only be applied for this Context. Default is False.
ways.api.reset_asset_classes(hierarchies=())[source]

Clear out the class(es) that is registered under a given hierarchy.

Parameters:hierarchies (iter[tuple[str]]) – All of the hierarchies to remove custom Asset classes for. If nothing is given, all hierarchies will be cleared.
ways.api.Action

alias of _Aktion

ways.api.add_action(action, name='', context='', assignment='master')[source]

Add a created action to this cache.

Parameters:
  • action (ways.api.Action) – The action to add. Action objects are objects that get passed a Context object and run a function.
  • name (str, optional) – A name to use with this action. The name must be unique to this hierarchy/assignment or it risks overriding another Action that might already exist at the same location. If no name is given, the name on the action is tried, instead.
  • context (ways.api.Context or str) – The Context or hierarchy of a Context to add this Action to.
  • assignment (str, optional) – The group to add this action to, Default: ‘master’.
Raises:
  • RuntimeError – If no hierarchy is given and no hierarchy could be found on the given action.
  • RuntimeError – If no name is given and no name could be found on the given action.
ways.api.trace_all_load_results()[source]

Get the load results of every plugin and descriptor.

If the UUID for a Descriptor cannot be found, Ways will automatically assign it a UUID.

Using this function we can check 1. What plugins that Ways found and tried to load. 2. If our plugin loaded and, if not, why.

Returns:The main dictionary has two keys, “descriptors” and “plugins”. Each key has an OrderedDict that contains the UUID of each Descriptor and plugin and their objects.
Return type:dict[str, collections.OrderedDict [str, dict[str]]]
ways.api.trace_actions(obj, *args, **kwargs)[source]

Get actions that are assigned to the given object.

Parameters:
Returns:

The actions in the hierarchy.

Return type:

list[ways.api.Action or callable]

ways.api.trace_action_names(obj, *args, **kwargs)[source]

Get the names of all actions available to a Ways object.

Parameters:
Returns:

The names of all actions found for the Ways object.

Return type:

list[str]

ways.api.trace_method_resolution(method, plugins=False)[source]

Show the progression of how a Context’s method is resolved.

Parameters:
  • method (callable) – Some function on a Context object.
  • plugins (bool, optional) – If False, the result at every step of the method will be returned. If True, the Plugin that created each result will be returned al along with the result at every step. Default is False.
Returns:

The plugin resolution at each step.

Return type:

list

ways.api.trace_actions_table(obj, *args, **kwargs)[source]

Find the names and objects of every action registered to Ways.

Parameters:
Returns:

The names and actions of an object.

Return type:

dict[str, ways.api.Action or callable]

ways.api.trace_assignment(obj)[source]

str: Get the assignment for this object.

ways.api.trace_context(obj)[source]

Get a Context, using some object.

This function assumes that the given object is a Ways class that only has 1 Context added to it (not several).

Parameters:obj – Some Ways object instance.
Returns:The found Context.
Return type:ways.api.Context or NoneType
ways.api.trace_hierarchy(obj)[source]

Try to find a hierarchy for the given object.

Parameters:obj (ways.api.Action or ways.api.AssetFinder or ways.api.Context or ways.api.Find) – The object to get the hierarchy of.
Returns:The hierarchy of some object.
Return type:tuple[str]
ways.api.get_action_hierarchies(action)[source]

Get the Context hierachies that this Action is registered for.

Note

get_action_hierarchies will return every Action that matches the given Action name. So if multiple classes/functions are all registered under the same name, then every hierarchy that those Actions use will be returned. However, if a object like a function or class that was registered, only that object’s hierarchies will be returned.

Parameters:action (str or class or callable) – The action to get the hierachies of.
Returns:The hierarchies for the given Action.
Return type:set[tuple[str]]
ways.api.get_all_action_hierarchies()[source]

Organize every Action that is registered into Ways by object and hierarchy.

Returns:
dict[str: str or set]]:
Actions are stored as either classes or functions. Each Action’s value is a dict which contains the hierachies that the Action is applied to and its registered name.
Return type:dict[class or callable
ways.api.get_all_hierarchies()[source]

set[tuple[str]]: The Contexts that have plugins in our environment.

ways.api.get_child_hierarchies(hierarchy)[source]

list[tuple[str]]: Get hierarchies that depend on the given hierarchy.

ways.api.get_child_hierarchy_tree(hierarchy, full=False)[source]

Get all of the hierarchies that inherit the given hierarchy.

Examples

>>> get_all_hierarchy_trees(full=True)
>>> {
>>>     ('foo', ): {
>>>         ('foo', 'bar'): {
>>>             ('foo' 'bar', 'fizz'): {},
>>>         },
>>>         ('foo', 'something', 'buzz'): {
>>>             ('foo', 'something', 'buzz', 'thing'): {},
>>>         },
>>>     },
>>> }
>>> get_all_hierarchy_trees(full=False)
>>> {
>>>     'foo': {
>>>         'bar': {
>>>             'fizz': {},
>>>         },
>>>         'something': {
>>>             'buzz': {
>>>                 'thing': {},
>>>             },
>>>         },
>>>     },
>>> }
Parameters:
  • hierarchy (tuple[str]) – The hierarchy to get the child hierarchy items of.
  • full (bool, optional) – If True, each item in the dict will be its own hierarchy. If False, only a single part will be written. See examples for details. Default is False.
Returns:

The entire hierarchy.

Return type:

collections.defaultdict[str]

ways.api.get_all_hierarchy_trees(full=False)[source]

Get a description of every Ways hierarchy.

Examples

>>> get_all_hierarchy_trees(full=True)
>>> {
>>>     ('foo', ): {
>>>         ('foo', 'bar'): {
>>>             ('foo' 'bar', 'fizz'): {},
>>>         },
>>>         ('foo', 'something', 'buzz'): {
>>>             ('foo', 'something', 'buzz', 'thing'): {},
>>>         },
>>>     },
>>> }
>>> get_all_hierarchy_trees(full=False)
>>> {
>>>     'foo': {
>>>         'bar': {
>>>             'fizz': {},
>>>         },
>>>         'something': {
>>>             'buzz': {
>>>                 'thing': {},
>>>             },
>>>         },
>>>     },
>>> }
Parameters:full (bool, optional) – If True, each item in the dict will be its own hierarchy. If False, only a single part will be written. See examples for details. Default is False.
Returns:The entire hierarchy.
Return type:collections.defaultdict[str]
class ways.api.FileDescriptor(items)[source]

Bases: object

A generic class that creates Plugin objects from a file, on-disk.

Note

Any FileDescriptor class that returns back Plugin objects is valid (Descriptors can query from a database, locally on file, etc, etc. It’s all good) except there is one major requirement. FileDescriptor-like objects cannot append asynchronously. In other words, If a FileDescriptor manages threads that each find Plugin objects and append to a list of Plugin objects whenever each thread finishes, the Plugin objects might append out of order - which will create results that will be hard to debug.

It’s recommended to not use threading at all unless this return process is managed (like with a queue or some other kind of idea).

classmethod filter_plugin_files(items)[source]

Only get back the files that are likely to be plugin files.

get_plugin_info(path)[source]

Given some file path, get its metadata info.

Parameters:path (str) – The path to some directory containing plugin objects.
Returns:The information about this plugin path.
Return type:dict[str]
get_plugins(items=None)[source]

Get the Plugin objects that this instance is able to find.

Note

This object will sort the items it is given before retrieving its Plugin objects so files/folders that are given different priorities depending on how their paths are named.

Parameters:items (iterable[str] or str) – The paths that this FileDescriptor looks for to find Plugin objects. If not items are given, the instance’s stored items are used, instead.
Returns:The plugins.
Return type:list[ways.api.Plugin]
classmethod get_supported_extensions()[source]

list[str]: The Plugin file extensions.

class ways.api.FolderDescriptor(items)[source]

Bases: ways.base.descriptor.FileDescriptor

A generic abstraction that helps find Plugin objects for our code.

Note

Any FileDescriptor class that returns back Plugin objects is valid (Descriptors can query from a database, locally on file, etc, etc. It’s all good) except there is one major requirement. FileDescriptor-like objects cannot append asynchronously. In other words, If a FileDescriptor manages threads that each find Plugin objects and append to a list of Plugin objects whenever each thread finishes, the Plugin objects might append out of order - which will create results that will be hard to debug.

It’s recommended to not use threading at all unless this return process is managed (like with a queue or some other kind of idea).

class ways.api.GitLocalDescriptor(path, items, branch='master')[source]

Bases: ways.base.descriptor.FolderDescriptor

An object to describe a local git repository.

This class conforms its input to files that its base class can read and then calls it. Otherwise that, it’s not special.

class ways.api.GitRemoteDescriptor(url, items, path='', branch='master')[source]

Bases: ways.base.descriptor.GitLocalDescriptor

A Descriptor that clones an online Git repository.

class ways.api.ContextParser(context)[source]

Bases: object

A class that’s used to fill out missing values in a Context’s mapping.

Some quick terms: If you see the word ‘token’, it means a piece of a string that needs to be filled out, such as ‘some_{TOKEN}_here’.

A field is the token + its information. For example, if the token being filled out is optional or if input to a token is valid.

This class is meant to expand and resolve the tokens inside the mapping of a Context object.

get_all_mapping_details()[source]

Get the combined mapping details of this Context.

Note

The “true” combined mapping details of our Context is actually just Context.get_mapping_details(). This method can produce different results because it is yielding/updating Context.get_mapping_details() with all of its plugin’s data. Use with caution.

Returns:The combined mapping_details of our Context and plugins.
Return type:dict[str]
get_child_tokens(token)[source]

Find the child tokens of a given token.

Parameters:token (str) – The name of the token to get child tokens for.
Returns:
The child tokens for the given token. If the given token
is not a parent to any child tokens, return nothing.
Return type:list[str]
get_mapping_details()[source]

Get the parse-mapping details of our entire Context.

Basically, we take the collection of all of the mapping details of the Context, as is, which we know is the “sum” of all of the Context’s plugin’s mapping_details. But we also yield each plugin individually, in case some information was lost, along the way.

Yields:dict[str] – The mapping details of this Context.
get_required_tokens()[source]

list[str]: Get the tokens for this Context that must be filled.

get_str(resolve_with='', depth=-1, holdout=None, groups=None, display_tokens=False)[source]

Create a string of the Context’s mapping.

Note

holdout and groups cannot have any common token names.

Parameters:
  • resolve_with (iterable[str] or str, optional) – The types of ways that our parser is allowed to resolve a path. These are typically some combination of (‘glob’, ‘regex’, ‘env’) are are defined with our Plugin objects that make up a Context.
  • depth (int, optional) – The number of times this method are allowed to expand the mapping before it must return it. If depth=-1, this method will expand mapping until there are no more tokens left to expand or no more subtokens to expand with. Default: -1.
  • holdout (set[str], optional) – If tokens (pre-existing or expanded) are in this list, they will not be resolved. Default is None.
  • groups (dict[str, str] or iterable[str, str], optional) – A mapping of token names and a preferred token value to substitute it with. This variable takes priority over all types of resolve_with types. Default is None.
  • display_tokens (bool, optional) – If True, the original name of the token will be included in the output of the mapping, even it its contents are expanded. Example: ‘/some/{JOB}/here’ -> r’/some/(?P<JOB>w+_d+)/here’. It’s recommended to keep this variable as False because the syntax used is only regex-friendly. But if you really want it, it’s there. Default is False.
Raises:
  • ValueError – If groups got a bad value.
  • ValueError – If groups and holdout have any common elements. It’s impossible to know what to do in that case because both items have conflicting instructions.
Returns:

The resolved string.

Return type:

str

get_token_parse(name, parse_type)[source]

Get the parse expression for some token name.

Parameters:
  • name (str) – The name of the token to get parse details from.
  • parse_type (str) – The engine type whose expression will be returned
Returns:

The parse expression used for the given token.

get_tokens(required_only=False)[source]

Get the tokens in this instance.

Parameters:required_only (bool, optional) – If True, do not return optional tokens. If False, return all tokens, required and optional. Default is False.
Returns:The requested tokens.
Return type:list[str]
get_value_from_parent(name, parent, parse_type)[source]

Get the value of a token using another parent token.

Parameters:
  • name (str) – The token to get the value of.
  • parent (str) – The parent token that is believed to have a value. If it has a value, it is used to parse and return a value for the name token.
  • parse_type (str) – The parse engine to use.
Returns:

The value of the name token.

is_valid(token, value, resolve_with='regex')[source]

Check if a given value will work for some Ways token.

Parameters:
  • token (str) – The token to use to check for the given value.
  • value – The object to check for validity.
  • resolve_with (str, optional) – The parse type to use to check if value is valid for token. Only ‘regex’ is supported right now. Default: ‘regex’.
Returns:

If the given value was valid.

Return type:

bool

classmethod resolve_with_tokens(mapping, tokens, details, options, groups, display_tokens)[source]

Substitute tokens in our mapping for anything that we can find.

Parameters:
  • mapping (str) – The path that will be resolved and substituted.
  • tokens (list[str]) – The pieces inside of the mapping to resolve.
  • details (dict[str]) – All of the token/subtoken information available to resolve the tokens in this mapping.
  • options (list[str]) – The different ways to resolve the tokens.
  • groups (dict[str, str] or iterable[str, str], optional) – A mapping of token names and a preferred token value to substitute it with. This variable takes priority over all types of resolve_with types. Default is None.
  • display_tokens (bool, optional) – Whether or not to add regex (?P<TOKEN_NAME>) tags around all of our resolved text.
Returns:

The resolved mapping.

Return type:

str

ways.api.add_descriptor(description, update=True)[source]

Add an object that describes the location of Plugin objects.

Parameters:
  • description (dict or str) – Some information to create a descriptor object from. If the descriptor is a string and it is a directory on the path, ways.api.FolderDescriptor is returned. If it is an encoded URI, the string is parsed into a dict and processed. If it’s a dict, the dictionary is used, as-is.
  • update (bool, optional) – If True, add this Descriptor’s plugins to Ways. If False, the user must register a Descriptor’s plugins. Default is True.
ways.api.add_search_path(description, update=True)

Add an object that describes the location of Plugin objects.

Parameters:
  • description (dict or str) – Some information to create a descriptor object from. If the descriptor is a string and it is a directory on the path, ways.api.FolderDescriptor is returned. If it is an encoded URI, the string is parsed into a dict and processed. If it’s a dict, the dictionary is used, as-is.
  • update (bool, optional) – If True, add this Descriptor’s plugins to Ways. If False, the user must register a Descriptor’s plugins. Default is True.
ways.api.add_plugin(path)[source]

Load the Python file as a plugin.

Parameters:path (str) – The absolute path to a valid Python file (py or pyc).
ways.api.get_all_plugins()[source]

list[ways.api.Plugin]: Every registered plugin.

ways.api.init_plugins()[source]

Create the Descriptor and Plugin objects found in our environment.

This method ideally should only ever be run once, when Ways first starts.

class ways.api.Find(context)[source]

Bases: ways.core.compat.DirMixIn, object

A wrapper around a Context object that provides some basic syntax-sugar.

The syntax of using Context objects is clunky. This class is meant to help. See the second and last example, for details.

Example

>>> context = Context('/some/context')
>>> command = context.get_action('get_assets')
>>> command()
>>> # ['/some/asset1.tif', '/some/asset2.tif', '/some/asset2.tif']

Example

>>> # If an action is meant to return back an iterable object and the
>>> # action that it gets back is None, that can cause immediate problems
>>> #
>>> context = Context('/some/context')
>>> command = context.get_action('get_assets')  # Returns None
>>> for asset in command():
>>>     print(asset)
>>> # The above code will TypeError error if get_action returns None

Example

>>> # The best you can do is this
>>> context = Context('/some/context')
>>> command = context.get_action('get_assets') or lambda: []
>>> for asset in command():
>>>     print(asset)
>>> # The above code will not error but it's pretty verbose compared to
>>> # what we're actually trying to accomplish.

Example

>>> # Here is (IMO) the best solution
>>> context = Context('/some/context')
>>> find = finder.Find(context)
>>> # Returns [] even if get_assets isn't defined
>>> # because get_assets is listed in Finder(context).defaults
>>> #
>>> for asset in find.get_assets():
>>>     print(asset)
classmethod add_to_defaults(name, value, hierarchy=None)[source]

Add default value if an Action name is missing.

Parameters:
  • name (str) – The name of the Action to add a default value for.
  • value – The object to add as the default return value for a missing Action.
  • hierarchy (tuple[str] or str, optional) – The location to put these default values. If no hierarchy is given, (‘default’, ) is used, instead.
classmethod clear()[source]

Remove all stored default values from this class.

defaults = defaultdict(None, {('default',): {}})
class ways.api.AssetFinder(finder, asset)[source]

Bases: ways.core.compat.DirMixIn, object

A class that wraps a Find class with the current asset.

Ways Action objects don’t assume anything about their input. This is normally a good thing because it keeps Actions flexible. But if we’re working with an Action that expects an Asset object, we’d have to do this all the time:

Example

>>> asset = resource.get_asset({'info': 'here'}, context='some/context')
>>> output = asset.context.actions.get_foo(action, some='other', args=4)

Gross, right?

So instead what we do is add AssetFinder as an ‘actions’ property and then forcefully pass the Asset as the first argument to Actions.

Example

>>> asset = resource.get_asset({'info': 'here'}, context='some/context')
>>> output = asset.actions.get_foo(some='other', args=4)

That’s much better.