Skip to content

Commit

Permalink
merge --squash with feature_additions branch - Added nwe functions an…
Browse files Browse the repository at this point in the history
…d troubleshooting.rst. Also tightened up the docs a bit
  • Loading branch information
ColinKennedy committed Nov 12, 2017
1 parent 3f286e9 commit 94cb0c3
Show file tree
Hide file tree
Showing 38 changed files with 3,085 additions and 1,394 deletions.
2 changes: 1 addition & 1 deletion docs/context_advanced.rst
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ because its syntax is harder to follow
uses:
- foo/bar
Appending with an absolute plugin is much simpler
Appending with an absolute plugin is much simpler.

.. code-block :: yaml
Expand Down
15 changes: 10 additions & 5 deletions docs/descriptors.rst
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,20 @@ when our cache unpacks this descriptor string, the result is a dict

descriptor_info = {
'create_using': 'ways.api.GitLocalDescriptor',
'uuid': 'some_unique_string-we-can_search_for-later',
'path': '/some/path/on/disk',
'items': ('plugins', ),
}

"create_using" is a the only reserved key in our dict. Ways uses
"create_using" to import the Descriptor object.
All other key/value pairs are passed to the Descriptor, directly.
It's worth noting that create_using can be any callable Python object. It could
be a function or a class, for example.
"create_using" and "uuid" are the only reserved key in our dict for all custom
Descriptors. Ways uses "create_using" to import the Descriptor object. "uuid"
is used to get the Descriptor later. For example, if a Descriptor failed to
load and you wanted to get its load results to find out why it failed to load,
you'd use the value in "uuid" to do it.

Excluding "create_using" and "uuid", all other key/value pairs are passed
to the Descriptor, directly. It's worth noting that create_using can be any
callable Python object. It could be a function or a class, for example.

Knowing what you now know about Descriptors, the previous example with the 4
different ways to load Descriptors could technically be rewritten as URL strings.
Expand Down
7 changes: 0 additions & 7 deletions docs/finder_common.rst

This file was deleted.

94 changes: 28 additions & 66 deletions docs/getting_started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,18 @@ Now that plugin_sheet.yml exists, lets add a "Hello World!" plugin to it.
hierarchy: 'some/context'

At this point, we've made our first plugin in our first Plugin Sheet.
Now you can open a Python interpreter or another file and use it, as a Context.
Now you can open a Python interpreter or import it into another file and use
it, as a ways.api.Context.

Instantiate your new Context
----------------------------

::

import ways.api
ways.api.get_context('some/context')
context = ways.api.get_context('some/context')

If get_context did not return None, congratulations, Ways is ready to use.
If context is not None, congratulations, Ways is ready to use.

Adding features to Context objects
----------------------------------
Expand Down Expand Up @@ -94,7 +95,8 @@ same hierarchy.

In the above example, we have a Context that initializes with some metadata,
we add to the metadata, and then we retrieve it in another function without
passing the Context into it.
passing the Context into it. This works because there's only ever one instance
of a Context object and you can add anything to its data.

There's a lot more to how Plugin objects are defined. Including Context
inheritance, relative plugins, and OS-aware plugins. To know more, Check out
Expand All @@ -109,12 +111,12 @@ now we'll extend it using an Asset object.

If Context objects are branches on a tree, think of Asset objects as the leaves.
Meaning, Context objects describe a range of information and Asset objects are
specific points along that range.
specific points along that range. There can only be 1 of any Context but there
could be any number of Asset objects.

Creating an Asset object is more or less the same as creating a Context. The
main difference is that any part of a Context's mapping that is an unfilled
Token (i.e. in our above example, "{JOB}"), we need to define it while creating
the Asset.
Token (in our above example "{JOB}" is unfilled), we need to define it.

::

Expand All @@ -129,7 +131,7 @@ the Asset.
# All 3 of these syntaxes create the same Asset object
asset1 = ways.api.get_asset((('JOB', 'foo'), ), 'some/context')
asset2 = ways.api.get_asset({'JOB': 'foo'}, 'some/context')
asset3 = ways.api.get_asset(path, 'some/context')
asset3 = ways.api.get_asset('/jobs/foo/here', 'some/context')
print(asset1.get_str())
# Result: '/jobs/foo/here'
print(asset1.get_value('JOB'))
Expand All @@ -152,9 +154,9 @@ both classes have very few methods. Ways tries to not assume how
you'll use Context and Asset objects and instead lets you to extend the
object's interfaces at runtime, using Actions.

To create an Action for our original example, create a new file - we'll call
ours action.py. Add the path to action.py into the WAYS_PLUGINS environment
variable.
To create an Action for our original example, create a new file name anything -
we'll call ours action.py. Add the path to action.py into the WAYS_PLUGINS
environment variable.

Now just add a new class in action.py, have it inherit from ways.api.Action,
and implement two methods.
Expand Down Expand Up @@ -189,11 +191,15 @@ action.py
def get_hierarchy(cls):
return 'some/context'

def __call__(self):
def __call__(self, obj):
'''Do something.'''
return ['/library', 'library/grades', 'comp', 'anim']

To use the Action that was just created, call it from a Context or Assset.
Note: __call__ takes at least one arg - the Context or Asset that called the
Action. Ways will pass the caller object to this variable before any of the
user's args/kwargs.

To use the Action that was just created, call it from a Context or Asset.

::

Expand All @@ -206,7 +212,7 @@ can also use a regular function and register it.

::

def some_action():
def some_action(obj):
return ['/library', 'library/grades', 'comp', 'anim']

context = ways.api.get_context('some/context')
Expand All @@ -232,70 +238,26 @@ Context and Asset Actions
We've been using Context.actions this whole time but Asset objects have an
"actions" property, too.

ways.api.Asset.actions behaves differently than ways.api.Context.actions.

Asset.actions will always assume that the Action's first argument will take the
current Asset object. Context.actions doesn't assume anything about an Action's
parameters.

If we have an Action like this:


::

> cat plugin_sheet.yml
plugins:
job:
hierarchy: 'some/context'
mapping: /jobs/{JOB}/here

action.py

::

import ways.api

class AnotherAction(ways.api.Action):

'''A subclass that will automatically be registered by Ways.'''

name = 'get_info'

@classmethod
def get_hierarchy(cls):
return 'some/context'

def __call__(self, shot=None):
'''Do something.'''
return ['/library', 'library/grades', 'comp', 'anim']

To call it from an Asset, all we have to write is this:

::

asset = ways.api.get_asset({'JOB': 'foo'}, context='some/context')
asset.actions.get_info()

Notice that AnotherAction.__call__ takes an argument but we call get_info with
no args. That's because the Asset object that calls it is being passed as the
first arg, since we used Asset.actions. With Context.actions, nothing is passed
- your args are left unmodified.
Actions called from an Asset object behave the same a Context objects. The only
difference is that the first arg that get's passed to the Actions object will
be the instance of Asset that called it, not the Context.

If we want to call get_info from a Context, we still can, it's just more work.
If we want to call get_info from an Asset instance and pass it the Context,
we still can.

::

asset = ways.api.get_asset({'JOB': 'something'}, context='some/context')

# Using the Context object
context = ways.api.get_context('some/context')
context.actions.get_info(asset)
context.actions.get_info() # get_info will pass 'context'

# Using the Context located in the Asset object
asset.context.actions.get_info(asset)
asset.context.actions.get_info() # get_info will pass 'asset.Context'

# This is still the preferred way, most of the time
asset.actions.get_info()
asset.actions.get_info() # get_info will pass 'asset'

The most powerful way to chain Actions together is to have Action objects
return other Context/Asset/Action objects. Actions have very few rules
Expand Down
3 changes: 2 additions & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ API Details
.. toctree::
Descriptors <descriptors>
Advanced Contexts <context_advanced>
Troubleshooting <troubleshooting>

Appendices
----------
Expand All @@ -51,5 +52,5 @@ Modules
.. toctree::
:maxdepth: 4

Module Documentation <ways>
API Documentation <ways>

22 changes: 20 additions & 2 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,26 @@
alabaster==0.7.10
Babel==2.5.1
certifi==2017.7.27.1
chardet==3.0.4
docutils==0.14
future==0.16.0
gitdb2==2.0.3
GitPython==2.1.7
pockets==0.5.1
idna==2.6
imagesize==0.7.1
Jinja2==2.9.6
MarkupSafe==1.0
pathlib==1.0.1
Pygments==2.2.0
pylev==1.3.0
pytz==2017.3
PyYAML==3.12
requests==2.18.4
six==1.11.0
smmap2==2.0.3
sphinxcontrib-napoleon==0.6.1
snowballstemmer==1.2.1
Sphinx==1.6.5
sphinxcontrib-websupport==1.0.1
typing==3.6.2
urllib3==1.22
yamlordereddictloader==0.4.0

0 comments on commit 94cb0c3

Please sign in to comment.