# General advices and troubleshooting

## Getting code samples

Yapsy is used enough for your favorite search provider to have good chances of finding some examples of yapsy being used in the wild.

However if you wonder how a specific functionality can be used, you can also look at the corresponding unit test (in the test folder packaged with yapsy’s sources).

## Use the logging system

Yapsy uses Python’s standard `logging` module to record most important events and especially plugin loading failures.

When developping an application based on yapsy, you’ll benefit from looking at the ‘debug’ level logs, which can easily be done from your application code with the following snippet:

    import logging
    logging.basicConfig(level=logging.DEBUG)

Also, please note that yapsy uses a named logger for all its logs, so that you can selectively activage debug logs for yapsy with the following snippet:

    import logging
    logging.getLogger('yapsy').setLevel(logging.DEBUG)

## Categorization by inheritance caveat

If your application defines various categories of plugins with the yapsy’s built-in mechanism for that, please keep in mind the following facts:

> - a plugin instance is attributed to a given category by looking if it is an instance, even via a subclass, of the class associated to this category;

> - a plugin may be attributed to several categories.

Considering this, and if you consider using several categories, you should consider the following tips:

> - don’t associate any category to ``IPlugin`` (unless you want all plugins to be attributed to the corresponding category)

> - design a specific subclass of `IPlugin` for each category

> - if you want to regroup plugins of some categories into a common category: do this by attributing a subclass of `IPlugin` to the common category and attribute to the other categories specific subclasses to this intermediate mother class so that the plugin class inheritance hierarchy reflects the hierarchy between categories (and if you want something more complex that a hierarchy, you can consider using mixins).

## Plugin class detection caveat

There must be only one plugin defined per module. This means that you can’t have two plugin description files pointing at the same module for instance.

Because of the “categorization by inheritance” system, you musn’t directly import the subclass of `IPlugin` in the main plugin file, instead import its containing module and make your plugin class inherit from `ContainingModule.SpecificPluginClass` as in the following example.

The following code won’t work (the class `MyBasePluginClass` will be detected as the plugin’s implementation instead of `MyPlugin`):

    from myapp.plugintypes import MyBasePluginClass

    class MyPlugin(MyBasePluginClass):
        pass

Instead you should do the following:

    import myapp.plugintypes as plugintypes

    class MyPlugin(plugintypes.MyBasePluginClass):
        pass

## Plugin packaging

When packaging plugins in a distutils installer or as parts of an application (like for instance with py2exe), you may want to take care about the following points:

- when you set specific directories where to look for plugins with a hardcoded path, be very carefully about the way you write these paths because depending on the cases using ``__file__`` or relative paths may be unreliable. For instance with py2exe, you may want to follow the tips from the Where Am I FAQ.

- you’d should either package the plugins as plain Python modules or data files (if you want to consider you application as the only module), either using the dedicated setup argument for py2exe or using distutils’ MANIFEST.in

- if you do package the plugins as data files, make sure that their dependencies are correctly indicated as dependencies of your package (or packaged with you application if you use py2exe).

See also a more detailed example for py2exe on Simon on Tech’s Using python plugin scripts with py2exe.

## Code conventions

If you intend to modify yapsy’s sources and to contribute patches back, please respect the following conventions:

- CamelCase (upper camel case) for class names and functions

- camelCase (lower camel case) for methods

- UPPERCASE for global variables (with a few exceptions)

- tabulations are used for indentation (and not spaces !)

- unit-test each new functionality