From 5563c7f66b082b1f1934dff8832ab444db0fe2aa Mon Sep 17 00:00:00 2001 From: Marcus Ottosson Date: Thu, 2 Oct 2014 11:52:48 +0100 Subject: [PATCH 1/2] Updated API documentation and optional plug-ins (#92) implemented. --- docs/config.rst | 7 - docs/index.rst | 310 ++++++++++++++++++++++++++++++++++++++++++-- docs/main.rst | 22 ---- docs/overview.rst | 14 -- docs/plugin.rst | 49 ------- docs/reference.rst | 18 --- pyblish/__init__.py | 32 +++-- pyblish/api.py | 5 +- pyblish/error.py | 18 +-- pyblish/main.py | 114 ++++++++++------ pyblish/plugin.py | 137 +++++++++++++------- 11 files changed, 493 insertions(+), 233 deletions(-) delete mode 100644 docs/config.rst delete mode 100644 docs/main.rst delete mode 100644 docs/overview.rst delete mode 100644 docs/plugin.rst delete mode 100644 docs/reference.rst diff --git a/docs/config.rst b/docs/config.rst deleted file mode 100644 index 216d6469..00000000 --- a/docs/config.rst +++ /dev/null @@ -1,7 +0,0 @@ - -Config -====== - -The config module wraps the corresponding `config.yaml` to provide for dot-syntax access to its members. - -See the `guide`_ for information on how to use it. \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index 10e508e6..90244957 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,22 +1,306 @@ -Documentation Overview -====================== +API +=== -Welcome to the documentation of Pyblish v\ |version|. +API documentation for Pyblish v\ |version|. -Contents: -.. toctree:: - :maxdepth: 1 +Objects +^^^^^^^ - overview - reference +.. module:: pyblish.plugin +Central objects used throughout Pyblish. +.. autosummary:: + :nosignatures: -Indices and tables -================== + Context + Instance + Plugin + Selector + Validator + Extractor + Conformer -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` +Functions +^^^^^^^^^ +Helper utilities. + +.. autosummary:: + :nosignatures: + + discover + plugin_paths + registered_paths + configured_paths + environment_paths + register_plugin_path + deregister_plugin_path + deregister_all + plugins_by_family + plugins_by_host + instances_by_plugin + +Configuration +^^^^^^^^^^^^^ + +.. module:: pyblish + +.. autosummary:: + :nosignatures: + + Config + +Library +^^^^^^^ + +.. module:: pyblish.lib + +.. autosummary:: + :nosignatures: + + log + format_filename + +Exceptions +^^^^^^^^^^ + +Exceptions raised that are specific to Pyblish. + +.. module:: pyblish.error + +.. autosummary:: + :nosignatures: + + PyblishError + SelectionError + ValidationError + ExtractionError + ConformError + +.. module:: pyblish.plugin + +Context +------- + +The context is a contained of one or more instances along with metadata to describe them all; such as the current working directory or logged on user. + +.. autoclass:: Context + :members: + :undoc-members: + +Instance +-------- + +An instance describes one or more items in a working scene; you can think of it as the counter-part of a file on disk - once the file has been loaded, it's an `instance`. + +.. autoclass:: Instance + :members: + :undoc-members: + + +Plugin +------ + +As a plug-in driven framework, any action is implemented as a plug-in and this is the superclass from which all plug-ins are derived. The superclass defines behaviour common across all plug-ins, such as its internally executed method :meth:`Plugin.process` or it's virtual members :meth:`Plugin.process_instance` and :meth:`Plugin.process_context`. + +Each plug-in MAY define one or more of the following attributes prior to being useful to Pyblish. + +- :attr:`Plugin.hosts` +- :attr:`Plugin.optional` +- :attr:`Plugin.version` + +Some of which are MANDATORY, others which are OPTIONAL. See each corresponding subclass for details. + +- :class:`Selector` +- :class:`Validator` +- :class:`Extractor` +- :class:`Conformer` + + +.. autoclass:: Plugin + :members: + :undoc-members: + +Selector +-------- + +A selector finds instances within a working file. + +.. note:: The following attributes must be present when implementing this plug-in. + + - :attr:`Selector.hosts` + - :attr:`Selector.version` + +.. autoclass:: Selector + :members: + :undoc-members: + +Validator +--------- + +A validator validates selected instances. + +.. note:: The following attributes must be present when implementing this plug-in. + + - :attr:`Plugin.hosts` + - :attr:`Plugin.version` + - :attr:`Validator.families` + +.. autoclass:: Validator + :members: + :undoc-members: + +Extractor +--------- + +Extractors are responsible for serialising selected data into a format suited for persistence on disk. Keep in mind that although an extractor does place file on disk, it isn't responsible for the final destination of files. See :class:`Conformer` for more information. + +.. note:: The following attributes must be present when implementing this plug-in. + + - :attr:`Plugin.hosts` + - :attr:`Plugin.version` + - :attr:`Extractor.families` + +.. autoclass:: Extractor + :members: + :undoc-members: + +Conformer +--------- + +The conformer, also known as `integrator`, integrates data produced by extraction. + +Its responsibilities include: + +1. Placing files into their final destination +2. To manage and increment versions, typically involving a third-party versioning library. +3. To notify artists of events +4. To provide hooks for out-of-band processes + +.. note:: The following attributes must be present when implementing this plug-in. + + - :attr:`Plugin.hosts` + - :attr:`Plugin.version` + - :attr:`Conformer.families` + +.. autoclass:: Conformer + :members: + :undoc-members: + + +discover +-------- + +.. autofunction:: discover + +plugin_paths +------------ + +.. autofunction:: plugin_paths + +registered_paths +---------------- + +.. autofunction:: registered_paths + +configured_paths +---------------- + +.. autofunction:: configured_paths + +environment_paths +----------------- + +.. autofunction:: environment_paths + +register_plugin_path +-------------------- + +.. autofunction:: register_plugin_path + +deregister_plugin_path +---------------------- + +.. autofunction:: deregister_plugin_path + +deregister_all +-------------- + +.. autofunction:: deregister_all + +plugins_by_family +----------------- + +.. autofunction:: plugins_by_family + +plugins_by_host +---------------- + +.. autofunction:: plugins_by_host + +instances_by_plugin +------------------- + +.. autofunction:: instances_by_plugin + +.. module:: pyblish + +Config +------ + +.. autoclass:: Config + :members: + +.. module:: pyblish.lib + +log +--- + +.. autofunction:: log + + +format_filename +--------------- + +.. autofunction:: format_filename + + +.. module:: pyblish.error + + +PyblishError +------------ + +.. autoclass:: PyblishError + :members: + :undoc-members: + +SelectionError +-------------------- + +.. autoclass:: SelectionError + :members: + :undoc-members: + +ValidationError +--------------- + +.. autoclass:: ValidationError + :members: + :undoc-members: + +ExtractionError +--------------- + +.. autoclass:: ExtractionError + :members: + :undoc-members: + +ConformError +------------ + +.. autoclass:: ConformError + :members: + :undoc-members: diff --git a/docs/main.rst b/docs/main.rst deleted file mode 100644 index 6ea3e721..00000000 --- a/docs/main.rst +++ /dev/null @@ -1,22 +0,0 @@ - -Main -==== - -.. module:: pyblish.main - -.. autosummary:: - :nosignatures: - - select - validate - extract - conform - publish_all - -.. automodule:: pyblish.main - -.. autofunction:: pyblish.main.select -.. autofunction:: pyblish.main.validate -.. autofunction:: pyblish.main.extract -.. autofunction:: pyblish.main.conform -.. autofunction:: pyblish.main.publish_all diff --git a/docs/overview.rst b/docs/overview.rst deleted file mode 100644 index 1848df9c..00000000 --- a/docs/overview.rst +++ /dev/null @@ -1,14 +0,0 @@ -Overview -======== - -Pyblish is a plug-in driven automation framework for content, licensed under LGPLv3. - -- `Guide`_ -- `Docs`_ -- `Wiki`_ -- `Repository`_ - -.. _`Guide`: http://pyblish.com -.. _`Docs`: http://docs.pyblish.com -.. _`Wiki`: https://github.com/abstractfactory/pyblish/wiki -.. _`Repository`: https://github.com/abstractfactory/pyblish diff --git a/docs/plugin.rst b/docs/plugin.rst deleted file mode 100644 index 668a5ffa..00000000 --- a/docs/plugin.rst +++ /dev/null @@ -1,49 +0,0 @@ - -Plugins -======= - -.. module:: pyblish.backend.plugin - -.. autosummary:: - :nosignatures: - - Context - Instance - Plugin - Selector - Validator - Extractor - Conformer - discover - -.. autofunction:: pyblish.backend.plugin.discover -.. autofunction:: pyblish.backend.plugin.plugin_paths - -.. autofunction:: pyblish.backend.plugin.register_plugin_path -.. autofunction:: pyblish.backend.plugin.deregister_plugin_path -.. autofunction:: pyblish.backend.plugin.deregister_all - -.. autoclass:: pyblish.backend.plugin.AbstractEntity - :members: -.. autoclass:: pyblish.backend.plugin.Context - :members: -.. autoclass:: pyblish.backend.plugin.Instance - :members: - -.. autoclass:: pyblish.backend.plugin.Plugin - :members: -.. autoclass:: pyblish.backend.plugin.Selector - :members: -.. autoclass:: pyblish.backend.plugin.Validator - :members: -.. autoclass:: pyblish.backend.plugin.Extractor - :members: -.. autoclass:: pyblish.backend.plugin.Conformer - :members: - -.. autofunction:: pyblish.backend.plugin.plugins_by_family -.. autofunction:: pyblish.backend.plugin.plugins_by_host -.. autofunction:: pyblish.backend.plugin.instances_by_plugin - - -.. _`guide`: http://pyblish.com/#configuring-pyblish \ No newline at end of file diff --git a/docs/reference.rst b/docs/reference.rst deleted file mode 100644 index 168bc2ca..00000000 --- a/docs/reference.rst +++ /dev/null @@ -1,18 +0,0 @@ -.. _reference: - -Reference -========= - -Most of what Pyblish provides can be found in the :mod:`pyblish.backend.plugin` module. In it are two central objects - Context and Instance - along with four processors - Selector, Validator, Extractor and Conformer. - -The context is singular throughout the lifespan of a single publish and contains instances. An instance represents what may ultimately become one or more files on disk, such as a model or pointcache. A context then contains one or more of these, as governed by the contents of your current working file. - -The :mod:`main` module contains convenience functions, such as :mod:`main.select` that encapsulate multiple commands, such as :mod:`pyblish.backend.plugin.Context()` and :mod:`pyblish.backend.plugin.discover()`. - - -.. toctree:: - :maxdepth: 1 - - main - plugin - config \ No newline at end of file diff --git a/pyblish/__init__.py b/pyblish/__init__.py index 07c23096..cfc4da52 100644 --- a/pyblish/__init__.py +++ b/pyblish/__init__.py @@ -7,24 +7,38 @@ class Config(dict): - """Wrapper for config.yaml, user and custom configuration + """Wrapper for default-, user- and custom-configuration .. note:: Config is a singleton. Configuration is cascading in the following order; - _________ ________ ______ - | | | | | | - | Default | + | Custom | + | User | - |_________| |________| |______| + .. code-block:: bash + + _________ ________ ______ + | | | | | | + | Default | + | Custom | + | User | + |_________| |________| |______| In which `User` is being added last and thus overwrites any previous configuration. + Attributes: + DEFAULTCONFIG: Name of default configuration file + USERCONFIG: Name of user and custom configuration file + HOMEDIR: Absolute path to user's home directory + PACKAGEDIR: Absolute path to parent package of Config + USERCONFIGPATH: Absolute path to user configuration file + DEFAULTCONFIGPATH: Absolute path to default configuration file + + default: Access to default configuration + custom: Access to custom configuration + user: Access to user configuration + Usage: - >> config = Config() - >> for key, value in config.iteritems(): - .. assert key in config + >>> config = Config() + >>> for key, value in config.iteritems(): + ... assert key in config """ @@ -40,8 +54,8 @@ class Config(dict): log = logging.getLogger('pyblish.Config') default = dict() # Default configuration data - user = dict() # User configuration data custom = dict() # Custom configuration data + user = dict() # User configuration data def __new__(cls, *args, **kwargs): """Make Config into a singleton""" diff --git a/pyblish/api.py b/pyblish/api.py index 265f6e27..f90c12b0 100644 --- a/pyblish/api.py +++ b/pyblish/api.py @@ -25,9 +25,8 @@ from . import Config as _Config from .lib import log, format_filename from .error import ( - PyblishError, SelectionError, - ValidationError, ExtractionError, ConformError, - NoInstancesError) + PyblishError, SelectionError, ValidationError, + ExtractionError, ConformError, NoInstancesError) # For forwards-compatibility Integrator = Conformer diff --git a/pyblish/error.py b/pyblish/error.py index 29e4c622..81ca7e2c 100644 --- a/pyblish/error.py +++ b/pyblish/error.py @@ -1,22 +1,22 @@ class PyblishError(Exception): - pass - - -class NoInstancesError(PyblishError): - pass + """Baseclass for all Pyblish exceptions""" class ValidationError(PyblishError): - pass + """Baseclass for validation errors""" class SelectionError(PyblishError): - pass + """Baseclass for selection errors""" class ExtractionError(PyblishError): - pass + """Baseclass for extraction errors""" class ConformError(PyblishError): - pass + """Baseclass for conforming errors""" + + +class NoInstancesError(Exception): + """Raised if no instances could be found""" diff --git a/pyblish/main.py b/pyblish/main.py index 87f4c117..8193c3ad 100644 --- a/pyblish/main.py +++ b/pyblish/main.py @@ -11,7 +11,6 @@ currently handlers and restore then once finished. log: Current logger intro_message: Message printed upon initiating a publish. - """ from __future__ import absolute_import @@ -24,26 +23,12 @@ import pyblish.api TAB = " " -LOG_TEMPATE = "{tab}%(levelname)-8s %(message)s".format(tab=TAB) +LOG_TEMPATE = " %(levelname)-8s %(message)s" SCREEN_WIDTH = 80 logging_handlers = logging.getLogger().handlers[:] log = logging.getLogger('pyblish.main') -intro_message = """ -%s -pyblish version {version} -%s - -User Configuration @ {user_path} - -Available plugin paths: -{paths} - -Available plugins: -{plugins} -""" % ("-" * SCREEN_WIDTH, "-" * SCREEN_WIDTH) - __all__ = ['select', 'validate', 'extract', @@ -81,6 +66,7 @@ def _format_plugins(plugins): def publish(context=None, auto_repair=False, + include_optional=True, logging_level=logging.INFO, **kwargs): """Publish everything @@ -92,10 +78,10 @@ def publish(context=None, Arguments: context (pyblish.api.Context): Optional Context. Defaults to creating a new context each time. - types (list): Optional list of strings with names of types - to perform. Default is to perform all types. - delay (float): Add artificial delay to the processing - of each plug-in. Used in debugging. + auto_repair (bool): Whether or not to attempt to automatically + repair instances which fail validation. + include_optional (bool): Should validation include plug-ins + which has been defined as optional? logging_level (logging level): Optional level with which to log messages. Default is logging.INFO. @@ -109,11 +95,12 @@ def publish(context=None, _orders = kwargs.pop('orders', None) or (0, 1, 2, 3) assert not kwargs # There are no more arguments - obj = Publish(context) + obj = Publish(context, + auto_repair=auto_repair, + include_optional=include_optional, + logging_level=logging_level) - obj.logging_level = logging_level obj.orders = _orders - obj.repair = auto_repair obj.process() return obj.context @@ -154,33 +141,47 @@ def conform(*args, **kwargs): class Publish(object): - SCREEN_WIDTH = 80 - LOG_TEMPATE = " %(levelname)-8s %(message)s" - TAB = " " + """Publishing operator + + Arguments: + context (pyblish.api.Context): Optional Context. + Defaults to creating a new context each time. + auto_repair (bool): Whether or not to attempt to automatically + repair instances which fail validation. + include_optional (bool): Should validation include plug-ins + which has been defined as optional? + logging_level (logging level): Optional level with which + to log messages. Default is logging.INFO. + + """ log = logging.getLogger() - logging_level = logging.INFO @property def duration(self): return "%.2f" % (self._time['end'] - self._time['start']) - def __init__(self, context=None): + def __init__(self, + context=None, + auto_repair=False, + include_optional=True, + logging_level=logging.INFO): + if context is None: pyblish.api.Context.delete() context = pyblish.api.Context() self.context = context self.orders = (0, 1, 2, 3) - self.repair = False + self.repair = auto_repair + self.optional = include_optional + self.logging_level = logging_level self._plugins = pyblish.plugin.Plugins() self._conf = pyblish.api.config self._time = {'start': None, 'end': None} self._errors = list() - self._plugins.discover() - def process(self): """Process all instances within the given context""" self._time['start'] = time.time() @@ -298,12 +299,18 @@ def process_plugin(self, plugin): """ + errors = list() + + # Do not include optional plug-ins + if plugin.optional and self.optional is False: + self._log_plugin(plugin, suffix="(optional and skipped)") + return errors + self._log_plugin(plugin) # Initialise pretty-printing for plug-ins self._init_log() - errors = list() for instance, error in plugin().process(self.context): if error is None: continue @@ -345,7 +352,7 @@ def _init_log(self): self.log = logging.getLogger() self.log.handlers[:] = [] - formatter = logging.Formatter(self.LOG_TEMPATE) + formatter = logging.Formatter(LOG_TEMPATE) stream_handler = logging.StreamHandler() stream_handler.setFormatter(formatter) @@ -358,18 +365,43 @@ def _reset_log(self): self.log.handlers[:] = logging_handlers[:] self.log.setLevel(logging.INFO) - def _log_plugin(self, plugin): + def _log_plugin(self, plugin, suffix=''): if hasattr(plugin, 'name'): - name = "%s (%s)" % (plugin.__name__, plugin.name) + name = "%s (%s) %s" % (plugin.__name__, plugin.name, suffix) else: name = plugin.__name__ print "{plugin}...".format( - tab=self.TAB, + tab=TAB, plugin=name) def _log_intro(self): - message = intro_message.format( + """Provide a preface to what is about to happen + + Including: + - Pyblish version + - User configuration + - Available paths + - Available plug-ins + + """ + + intro = """ +{line} +pyblish version {version} +{line} + +User Configuration @ {user_path} + +Available plugin paths: +{paths} + +Available plugins: +{plugins} +""" + + message = intro.format( + line="-" * SCREEN_WIDTH, version=pyblish.__version__, user_path=(self._conf['USERCONFIGPATH'] if self._conf.user else "None"), @@ -407,7 +439,7 @@ def _log_error(self, instance, error): func=func)) self.log.error("{tab}{i}: {e} {tb}".format( - tab=self.TAB, + tab=TAB, i=instance, e=error, tb=traceback if traceback else '')) @@ -458,7 +490,7 @@ def _log_summary(self): conform_dirs = instance.data('conform_dirs') _message = "{tab}- \"{inst}\" ".format( - tab=self.TAB, + tab=TAB, inst=instance) _message += "processed by:" @@ -475,11 +507,11 @@ def _log_summary(self): if commit_dir: message += "{tab}Committed to: {dir}".format( - tab=self.TAB*2, dir=commit_dir) + "\n" + tab=TAB*2, dir=commit_dir) + "\n" if conform_dirs: message += "{tab}Conformed to: {dir}".format( - tab=self.TAB*2, dir=", ".join(conform_dirs)) + "\n" + tab=TAB*2, dir=", ".join(conform_dirs)) + "\n" print # newline print message diff --git a/pyblish/plugin.py b/pyblish/plugin.py index 5cd9dd14..c12b3937 100644 --- a/pyblish/plugin.py +++ b/pyblish/plugin.py @@ -63,6 +63,7 @@ class Plugins(list): """Plug-in manager""" def __init__(self, paths=None): self.paths = paths or plugin_paths() + self.discover() def discover(self, paths=None): self[:] = discover(paths=paths) @@ -98,11 +99,29 @@ def by_host(self, host): @pyblish.lib.log class Plugin(object): - """Abstract base-class for plugins""" + """Abstract base-class for plugins + + Attributes: + hosts: Mandatory specifier for which host application + this plug-in is compatible with. + version: Mandatory version for forwards-compatibility. + Pyblish is (currently not) using the version to allow + for plug-ins incompatible with a particular running + instance of Pyblish to co-exist alongside compatible + versions. + order: Order in which this plug-in is processed. This is + used internally to control which plug-ins are processed + before another so as to allow plug-ins to communicate + with each other. E.g. one plug-in may provide critical + information to another and so must be allowed to be + processed first. + + """ hosts = list() # Hosts compatible with plugin version = (0, 0, 0) # Current version of plugin order = None + optional = False def __str__(self): return type(self).__name__ @@ -113,19 +132,18 @@ def __repr__(self): def process(self, context): """Perform processing upon context `context` - process() retruns a generator with (instance, error), with - error defaulted to `None`. Each error is injected with a - stack-trace of what went wrong, accessible via error.traceback. - - If an instance contains the data "publish" and that data is - `False` the instance will not be processed. + .. note:: If an instance contains the data "publish" and that data is + `False` the instance will not be processed. Injected data during processing: - __is_processed__: Whether or not the instance was processed - __processed_by__: Plugins which processed the given instance + + - `__is_processed__`: Whether or not the instance was processed + - `__processed_by__`: Plugins which processed the given instance Returns: - Generator, yielding per instance + :meth:`process` returns a generator with (instance, error), with + error defaulted to `None`. Each error is injected with a + stack-trace of what went wrong, accessible via error.traceback. Yields: Tuple (Instance, Exception) @@ -183,12 +201,12 @@ def process(self, context): yield instance, err def process_context(self, context): - """Process context `context` + """Process `context` Implement this method in your subclasses whenever you need to process the full context. The principal difference here is that only one return value is required, exceptions are - handled gracefully by :meth:process above. + handled gracefully by :meth:`process` above. Returns: None @@ -215,7 +233,7 @@ def process_instance(self, instance): """ def process_all(self, context): - """Convenience method of the above :meth:process + """Convenience method of the above :meth:`process` Return: None @@ -238,51 +256,54 @@ class Validator(Plugin): Raises exception upon failure. + Attributes: + families: Supported families. + """ families = list() order = 1 - def fix(self): - """Optional auto-fix for when validation fails""" - class Extractor(Plugin): """Physically separate Instance from Host into corresponding resources By convention, an extractor always positions files relative the - current working file. Use the convenience :meth:commit() to maintain + current working file. Use the convenience :meth:`commit` to maintain this convention. + Attributes: + families: Supported families. + """ families = list() order = 2 - def commit(self, path, instance): - """Move path `path` relative current workspace + def compute_commit_directory(self, instance): + """Return commit directory for `instance` - Arguments: - path (str): Absolute path to where files are currently located; - usually a temporary directory. - instance (Instance): Instance located at `path` + The commit directory is derived from a template, located within + the configuration. The following variables are substituted at + run-time: - .. note:: Both `path` and `instance` are required for this operation, - but it doesn't make sense to include both as argument because - they say pretty much the same thing. + - pyblish: With absolute path to pyblish package directory + - prefix: With Config['prefix'] + - date: With date embedded into `instance` + - family: With instance embedded into `instance` + - instance: Name of `instance` + - user: Currently logged on user, as derived from `instance` - An alternative is to embed `path` into instance.set_data() prior - to running `commit()` but the path is ONLY needed during commit - and will become invalidated afterwards. + Arguments: + instance (Instance): Instance for which to compute a directory - How do we simplify this? Ultimately, the way in which files - end up in their final destination, relative the working file, - should be automated and not left up to the user. + Returns: + Absolute path to directory as string - """ + Raises: + ExtractorError: When data is missing from `instance` - if instance.context.data('current_file') is None: - raise ValueError("Cannot commit with data 'current_file'") + """ workspace_dir = instance.context.data('workspace_dir') if not workspace_dir: @@ -293,7 +314,7 @@ def commit(self, path, instance): date = instance.context.data('date') - # These two are assumed from built-in plugins + # This is assumed from default plugins assert date if not workspace_dir: @@ -307,11 +328,10 @@ def commit(self, path, instance): valid_name = pyblish.lib.format_filename(name) if name != valid_name: self.log.info("Formatting instance name: " - "\"%s\"-> \"%s\"" + "\"%s\" -> \"%s\"" % (name, valid_name)) name = valid_name - # Commit directory based on template, see config.yaml variables = {'pyblish': pyblish.lib.main_package_path(), 'prefix': config['prefix'], 'date': date, @@ -326,6 +346,20 @@ def commit(self, path, instance): commit_dir = commit_template.format(**variables) commit_dir = os.path.join(workspace_dir, commit_dir) + return commit_dir + + def commit(self, path, instance): + """Move path `path` relative current workspace + + Arguments: + path (str): Absolute path to where files are currently located; + usually a temporary directory. + instance (Instance): Instance located at `path` + + """ + + commit_dir = self.compute_commit_directory(instance=instance) + self.log.info("Moving {0} relative working file..".format(instance)) if os.path.isdir(commit_dir): @@ -345,7 +379,12 @@ def commit(self, path, instance): class Conformer(Plugin): - """Integrates publishes into a pipeline""" + """Integrates publishes into a pipeline + + Attributes: + families: Supported families. + + """ families = list() order = 3 @@ -388,7 +427,7 @@ def data(self, key=None, default=None): """ if key is None: - return self._data + return self._data.copy() return self._data.get(key, default) @@ -588,8 +627,6 @@ def register_plugin_path(path): To register a new directory, run this command along with the absolute path to where you're plug-ins are located. - .. note:: The path must exist. - Example: >>> import os >>> my_plugins = os.path.expanduser('~') @@ -677,9 +714,11 @@ def plugin_paths(): This function looks at the three potential sources of paths and returns a list with all of them together. - The sources are: Those registered using :func:`register_plugin_path`, - those appended to the `PYBLISHPLUGINPATH` and those added to - the user-configuration. + The sources are: + + - Registered paths using :func:`register_plugin_path`, + - Paths from the environment variable `PYBLISHPLUGINPATH` + - Paths from configuration Returns: list of paths in which plugins may be locat @@ -699,16 +738,18 @@ def plugin_paths(): def discover(type=None, regex=None, paths=None): - """Find plugins within _registered_paths plugin-paths + """Find plugins within exposed plugin-paths Arguments: - type (str): Only return plugins of specified type + type (str, optional):Only return plugins of specified type E.g. validators, extractors. In None is specified, return all plugins. - regex (str): Limit results to those matching `regex`. + regex (str, optional): Limit results to those matching `regex`. Matching is done on classes, as opposed to filenames, due to a file possibly hosting multiple plugins. + paths (list, optional): Paths to discover plug-ins from. + If no paths are provided, all paths are searched. """ From e34238390aaea0c16b10f5c10bbb1e522fe3c59f Mon Sep 17 00:00:00 2001 From: Marcus Ottosson Date: Thu, 2 Oct 2014 11:58:51 +0100 Subject: [PATCH 2/2] Updating CHANGES --- CHANGES | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES b/CHANGES index ad3e29d4..c031c677 100644 --- a/CHANGES +++ b/CHANGES @@ -25,6 +25,9 @@ Version 1.0.8 - Plug-ins for other hosts than the currently running host are discarded upon discovery. This means that they will be invisible to any incompatible host. +- Optional plug-ins. A plug-in may now be marked "optional" and thus + be ignored during processing by user-request using + pyblish.main.publish(include_optional=False) Version 1.0.7 -------------