Commits

Artur Barseghyan committed 828103a Draft

starting to work on python 3 support

Comments (0)

Files changed (14)

 build/
 builddocs/
 builddocs.zip
+example/media/news-images/
 example-builddocs/
 dist/
 src/django_werewolf.egg-info
 ^example/db/
 ^example/tmp/
 ^build/
+^example/media/news-images/
 ^builddocs/
 ^builddocs.zip
 ^example-builddocs/
+Package
+==================================
+django-werewolf
+
+Description
+==================================
+Item publishing workflow for Django (fully integrated into Django admin).
+
+Prerequisites
+===================================
+- Django 1.5.+
+- Python 2.7.+, 3.3.+
+
+Installation
+==================================
+1. Install django-werewolf into your virtual environment:
+
+    $ pip install django-werewolf
+
+2. Add `werewolf` to your ``INSTALLED_APPS``.
+
+That's all. See the `Usage and examples` section for more.
+
+Usage and examples
+==================================
+It's all about item publishing in a workflow. We have various `intermediate` statuses (work in-progress) and a
+final `status` which means that the item is actually published. Some users should be able to set the item status
+to `published`, some others not. This app allows you (and gives you a good working example with pre-configured
+Django environment) to write a custom workflow for publishing your items with minimal efforts.
+
+For a complete example of a working django-werewolf app see the
+(https://github.com/barseghyanartur/django-werewolf/tree/stable/example) and read the `readme.rst` of the `news`
+app.
+
+settings.py
+----------------------------------
+>>> # Workflow statuses; order is preserved.
+>>> WEREWOLF_STATUS_CHOICES = (
+>>>     ('new', gettext('New')), # New - this is how it's assigned to a writer.
+>>>     ('draft', gettext('Draft')), # Draft - this is how the writer works on it.
+>>>     ('ready', gettext('Ready')), # Ready to be reviewed by editor.
+>>>     ('reviewed', gettext('Reviewed')), # Reviewed by editor (means positive and ready to be published).
+>>>     ('published', gettext('Published')), # Published.
+>>> )
+>>>
+>>> # Published status.
+>>> WEREWOLF_STATUS_PUBLISHED = 'published'
+>>>
+>>> # When set to True, django-reversion is used.
+>>> WEREWOLF_USE_DJANGO_REVERSION = True
+
+news/models.py
+----------------------------------
+In the example below we have a basic news item model. We have Chief Editors with full access to news items, we
+have editors with less privelleges and Writers with very little privelleges. Chief Editors create articles,
+select an Editor and a Writer (both get notified) and let them work on the article. Writers can only set an
+article status to `new`, `draft` and `ready` (ready to be checked). Editors review the articles with status
+`ready` and set the status to `reviewed`. Chief Editors publish articles that are `reviewed`. Your
+implementation can be as custom as you want it. Think in Django user groups (``django.contrib.auth.models.Group``)
+and Django permissions system.
+
+NOTE: See the `Permission tuning` section.
+
+>>> from django.contrib.auth.models import User
+>>>
+>>> from werewolf.models import WerewolfBaseModel, WerewolfBaseMeta
+>>>
+>>> _chief_editors = {'groups__name__iexact': 'Chief editors'}
+>>> _editors = {'groups__name__iexact': 'Editors'}
+>>> _writers = {'groups__name__iexact': 'Writers'}
+>>>
+>>> class NewsItem(WerewolfBaseModel): # Important!
+>>>     title = models.CharField(_("Title"), max_length=100)
+>>>     body = models.TextField(_("Body"))
+>>>     date_published = models.DateTimeField(_("Date published"), \
+>>>                                           default=datetime.datetime.now())
+>>>     author = models.ForeignKey(User, verbose_name=_("Author"), related_name='authors', \
+>>>                                limit_choices_to=_writers)
+>>>     editor = models.ForeignKey(User, verbose_name=_("Editor"), related_name='editors', \
+>>>                                limit_choices_to=_editors)
+>>>     chief_editor = models.ForeignKey(User, verbose_name=_("Chief editor"), \
+>>>                                      related_name='chief_editors', \
+>>>                                      limit_choices_to=_chief_editors)
+>>>
+>>>     class Meta(WerewolfBaseMeta): # Important!
+>>>         verbose_name = "News item"
+>>>         verbose_name_plural = "News items"
+
+Or if you want to define custom permissions for your model as well, do extend the werewolf permissions as
+follows:
+
+>>> from werewolf.models import WerewolfBaseModel
+>>> from werewolf.utils import extend_werewolf_permissions
+>>>
+>>> class NewsItem(WerewolfBaseModel):
+>>>     # Your fields here
+>>>     class Meta:
+>>>         verbose_name = "News item"
+>>>         verbose_name_plural = "News items"
+>>>
+>>>         # Important!
+>>>         permissions = extend_werewolf_permissions(
+>>>             ('can_change_author', _("Can change author")),
+>>>             ('can_change_editor', _("Can change editor")),
+>>>             ('can_change_chief_editor', _("Can change chief editor"))
+>>>         )
+
+news/admin.py
+----------------------------------
+Basic admin for the news item model.
+
+NOTE: See the `Permission tuning` section.
+
+>>> from werewolf.admin import WerewolfBaseAdmin
+>>>
+>>> from news.models import NewsItem
+>>>
+>>> class NewsItemAdmin(WerewolfBaseAdmin):
+>>>     # Your code comes here
+>>>
+>>> admin.site.register(NewsItem, NewsItemAdmin)
+
+NOTE: If you override the ``queryset`` method of your model's admin class, make sure to see the source code
+of `werewolf.admin.WerewolfBaseAdmin.queryset` and copy the approach from there. Otherwise, your users with
+no permission to change the `published` status will be able to chgange the status of already published items
+to non-published statuses.
+
+news/views.py
+----------------------------------
+>>> from news.models import NewsItem
+>>>
+>>> def browse(request):
+>>>     news_items = NewsItem._default_manager.published()
+>>>     # Other code
+
+news/werewolf_triggers.py
+----------------------------------
+In order to perform extra tasks on status change, triggers are used. You simply make a new file in your app
+called `werewolf_triggers.py` and define custom classes that should be called when a ``status`` field of your
+model changes to a certain value. Each trigger should subclass the ``werewolf.triggers.WerewolfBaseTrigger``
+class.
+
+>>> from werewolf.triggers import WerewolfBaseTrigger, registry
+>>>
+>>> class StatusNewTrigger(WerewolfBaseTrigger):
+>>>     """
+>>>     News item status changed to `new`.
+>>>     """
+>>>     def process(self):
+>>>         # Your code
+>>>
+>>> class StatusReadyTrigger(WerewolfBaseTrigger):
+>>>     """
+>>>     News item status changed to `ready` (ready for review).
+>>>     """
+>>>     def process(self):
+>>>         # Your code
+>>>
+>>> # Triggers status change to `new` for news.newsitem model.
+>>> registry.register('news', 'newsitem', 'new', StatusNewTrigger)
+>>>
+>>> # Triggers status change to `ready` for news.newsitem model.
+>>> registry.register('news', 'newsitem', 'ready', StatusReadyTrigger)
+
+urls.py
+----------------------------------
+In order to have triggers autodiscovered, place the following code into your main `urls` module.
+
+>>> from werewolf import autodiscover as werewolf_autodiscover
+>>> werewolf_autodiscover()
+
+Permission tuning
+----------------------------------
+Have in mind our ``news.models.NewsItem`` model.
+
+1. Create three user groups:
+
+    a.  Chief editors (permissions listed):
+
+    - news | News item | Can add News item
+    - news | News item | Can change author
+    - news | News item | Can change chief editor
+    - news | News item | Can change editor
+    - news | News item | Can change News item
+    - news | News item | Can change status to draft
+    - news | News item | Can change status to new
+    - news | News item | Can change status to published
+    - news | News item | Can change status to ready
+    - news | News item | Can change status to reviewed
+    - news | News item | Can delete News item
+
+    b. Editors (permissions listed):
+
+    - news | News item | Can change News item
+    - news | News item | Can change author
+    - news | News item | Can change status to draft
+    - news | News item | Can change status to new
+    - news | News item | Can change status to ready
+    - news | News item | Can change status to reviewed
+
+    c. Writers (permissions listed):
+
+    - news | News item | Can change News item
+    - news | News item | Can change status to draft
+    - news | News item | Can change status to new
+    - news | News item | Can change status to ready
+
+3. Create three users:
+
+    - chief editor: Belongs to group `Chief editors`.
+    - editor: Belongs to group `Editors`.
+    - writer: Belongs to group `Writers`.
+
+4. Now log into the admin with different user and see your admin for the `News item` (created items with 
+   `chiefeditor` account, then view them with `editor` and `writer`.
+
+That's it. If somehow you don't see the new permissions (`Can change status to draft`,
+`Can change status to new`, etc) run a management command `syncww`:
+
+    $ ./manage.py syncww
+
+Running the example project
+==================================
+A working example of a django-werewolf app is available here:
+https://github.com/barseghyanartur/django-werewolf/tree/stable/example
+
+1. Go to example/example directory
+
+    $ cd example/example
+
+2. Install requirements (in your virtual environment)
+
+    $ pip install -r ../requirements.txt
+
+3. Copy local_settings.example to local_settings.py
+
+    $ cp local_settings.example local_settings.py
+
+4. Create the database
+
+    $ ./manage.py syncdb
+
+5. Run the project
+
+    $ ./manage.py runserver
+
+License
+==================================
+GPL 2.0/LGPL 2.1
+
+Support
+==================================
+For any issues contact me at the e-mail given in the `Author` section.
+
+Author
+==================================
+Artur Barseghyan <artur.barseghyan@gmail.com>

example/example/local_settings.example

 PROJECT_DIR = lambda base : os.path.abspath(os.path.join(os.path.dirname(__file__), base).replace('\\','/'))
 
 DEBUG = True
-DEBUG_TOOLBAR = True
+DEBUG_TOOLBAR = not True
 TEMPLATE_DEBUG = DEBUG
 
 DATABASES = {

example/example/news/models.py

         return self.status
     admin_status.allow_tags = True
     admin_status.short_description = _('Status')
+
+    def get_absolute_url(self):
+        """
+        Given just as an example.
+        """
+        return '/some/path/to/news-item/%s' % self.slug

example/requirements.txt

-Django==1.5.1
-Pillow==2.0.0
-argparse==1.2.1
+Django==1.5.2
+Pillow==2.1.0
 django-autoslug==1.6.1
-django-debug-toolbar==0.9.4
 django-lime==0.2
 django-reversion==1.6.5
 django-tinymce==1.5.1
 django-werewolf
-ipdb==0.7
-ipython==0.13.2
 python-dateutil==2.1
 pytz==2013b
-six==1.3.0
-wsgiref==0.1.2
+six==1.4.1
+python setup.py install
+python example/example/manage.py collectstatic --noinput --traceback -v 3
+python example/example/manage.py syncdb --noinput --traceback -v 3
+python example/example/manage.py migrate --noinput --traceback -v 3

readme.rst

-Package
-==================================
-django-werewolf
-
-Description
-==================================
-Item publishing workflow for Django (fully integrated into Django admin).
-
-Installation
-==================================
-1. Install django-werewolf into your virtual environment:
-
-    $ pip install django-werewolf
-
-2. Add `werewolf` to your ``INSTALLED_APPS``.
-
-That's all. See the `Usage and examples` section for more.
-
-Usage and examples
-==================================
-It's all about item publishing in a workflow. We have various `intermediate` statuses (work in-progress) and a
-final `status` which means that the item is actually published. Some users should be able to set the item status
-to `published`, some others not. This app allows you (and gives you a good working example with pre-configured django
-environment) to write a custom workflow for publishing your items with minimal efforts.
-
-For a complete example of a working django-werewolf app see the https://bitbucket.org/barseghyanartur/django-werewolf
-(example directory) and read the `readme.rst` of the `news` app.
-
-settings.py
-----------------------------------
->>> # Workflow statuses; order is preserved.
->>> WEREWOLF_STATUS_CHOICES = (
->>>     ('new', gettext('New')), # New - this is how it's assigned to a writer.
->>>     ('draft', gettext('Draft')), # Draft - this is how the writer works on it.
->>>     ('ready', gettext('Ready')), # Ready to be reviewed by editor.
->>>     ('reviewed', gettext('Reviewed')), # Reviewed by editor (means positive and ready to be published).
->>>     ('published', gettext('Published')), # Published.
->>> )
->>>
->>> # Published status.
->>> WEREWOLF_STATUS_PUBLISHED = 'published'
->>>
->>> # When set to True, django-reversion is used.
->>> WEREWOLF_USE_DJANGO_REVERSION = True
-
-news/models.py
-----------------------------------
-In the example below we have a basic news item model. We have Chief Editors with full access to news items, we have
-editors with less privelleges and Writers with very little privelleges. Chief Editors create articles, select an
-Editor and a Writer (both get notified) and let them work on the article. Writers can only set an article status to
-`new`, `draft` and `ready` (ready to be checked). Editors review the articles with status `ready` and set the status
-to `reviewed`. Chief Editors publish articles that are `reviewed`. Your implementation can be as custom as you want
-it. Think in Django user groups (``django.contrib.auth.models.Group``) and Django permissions system.
-
-NOTE: See the `Permission tuning` section.
-
->>> from django.contrib.auth.models import User
->>>
->>> from werewolf.models import WerewolfBaseModel, WerewolfBaseMeta
->>>
->>> _chief_editors = {'groups__name__iexact': 'Chief editors'}
->>> _editors = {'groups__name__iexact': 'Editors'}
->>> _writers = {'groups__name__iexact': 'Writers'}
->>>
->>> class NewsItem(WerewolfBaseModel): # Important!
->>>     title = models.CharField(_("Title"), max_length=100)
->>>     body = models.TextField(_("Body"))
->>>     date_published = models.DateTimeField(_("Date published"), default=datetime.datetime.now())
->>>     author = models.ForeignKey(User, verbose_name=_("Author"), related_name='authors', limit_choices_to=_writers)
->>>     editor = models.ForeignKey(User, verbose_name=_("Editor"), related_name='editors', limit_choices_to=_editors)
->>>     chief_editor = models.ForeignKey(User, verbose_name=_("Chief editor"), related_name='chief_editors', \
->>>                                      limit_choices_to=_chief_editors)
->>>
->>>     class Meta(WerewolfBaseMeta): # Important!
->>>         verbose_name = "News item"
->>>         verbose_name_plural = "News items"
-
-Or if you want to define custom permissions for your model as well, do extend the werewolf permissions as follows:
-
->>> from werewolf.models import WerewolfBaseModel
->>> from werewolf.utils import extend_werewolf_permissions
->>>
->>> class NewsItem(WerewolfBaseModel):
->>>     # Your fields here
->>>     class Meta:
->>>         verbose_name = "News item"
->>>         verbose_name_plural = "News items"
->>>
->>>         # Important!
->>>         permissions = extend_werewolf_permissions(
->>>             ('can_change_author', _("Can change author")),
->>>             ('can_change_editor', _("Can change editor")),
->>>             ('can_change_chief_editor', _("Can change chief editor"))
->>>         )
-
-news/admin.py
-----------------------------------
-Basic admin for the news item model.
-
-NOTE: See the `Permission tuning` section.
-
->>> from werewolf.admin import WerewolfBaseAdmin
->>>
->>> from news.models import NewsItem
->>>
->>> class NewsItemAdmin(WerewolfBaseAdmin):
->>>     # Your code comes here
->>>
->>> admin.site.register(NewsItem, NewsItemAdmin)
-
-NOTE: If you override the ``queryset`` method of your model's admin class, make sure to see the source code of
-`werewolf.admin.WerewolfBaseAdmin.queryset` and copy the approach from there. Otherwise, your users with no permission
-to change the `published` status will be able to chgange the status of already published items to non-published
-statuses.
-
-news/views.py
-----------------------------------
->>> from news.models import NewsItem
->>>
->>> def browse(request):
->>>     news_items = NewsItem._default_manager.published()
->>>     # Other code
-
-news/werewolf_triggers.py
-----------------------------------
-In order to perform extra tasks on status change, triggers are used. You simply make a new file in your app called
-`werewolf_triggers.py` and define custom classes that should be called when a ``status`` field of your model changes
-to a certain value. Each trigger should subclass the ``werewolf.triggers.WerewolfBaseTrigger`` class.
-
->>> from werewolf.triggers import WerewolfBaseTrigger, registry
->>>
->>> class StatusNewTrigger(WerewolfBaseTrigger):
->>>     """
->>>     News item status changed to `new`.
->>>     """
->>>     def process(self):
->>>         # Your code
->>>
->>> class StatusReadyTrigger(WerewolfBaseTrigger):
->>>     """
->>>     News item status changed to `ready` (ready for review).
->>>     """
->>>     def process(self):
->>>         # Your code
->>>
->>> # Triggers status change to `new` for news.newsitem model.
->>> registry.register('news', 'newsitem', 'new', StatusNewTrigger)
->>>
->>> # Triggers status change to `ready` for news.newsitem model.
->>> registry.register('news', 'newsitem', 'ready', StatusReadyTrigger)
-
-urls.py
-----------------------------------
-In order to have triggers autodiscovered, place the following code into your main `urls` module.
-
->>> from werewolf import autodiscover as werewolf_autodiscover
->>> werewolf_autodiscover()
-
-Permission tuning
-----------------------------------
-Have in mind our ``news.models.NewsItem`` model.
-
-1. Create three user groups:
-
-    a.  Chief editors (permissions listed):
-
-    - news | News item | Can add News item
-    - news | News item | Can change author
-    - news | News item | Can change chief editor
-    - news | News item | Can change editor
-    - news | News item | Can change News item
-    - news | News item | Can change status to draft
-    - news | News item | Can change status to new
-    - news | News item | Can change status to published
-    - news | News item | Can change status to ready
-    - news | News item | Can change status to reviewed
-    - news | News item | Can delete News item
-
-    b. Editors (permissions listed):
-
-    - news | News item | Can change News item
-    - news | News item | Can change author
-    - news | News item | Can change status to draft
-    - news | News item | Can change status to new
-    - news | News item | Can change status to ready
-    - news | News item | Can change status to reviewed
-
-    c. Writers (permissions listed):
-
-    - news | News item | Can change News item
-    - news | News item | Can change status to draft
-    - news | News item | Can change status to new
-    - news | News item | Can change status to ready
-
-3. Create three users:
-
-    - chief editor: Belongs to group `Chief editors`.
-    - editor: Belongs to group `Editors`.
-    - writer: Belongs to group `Writers`.
-
-4. Now log into the admin with different user and see your admin for the `News item` (created items with `chiefeditor`
-   account, then view them with `editor` and `writer`.
-
-That's it. If somehow you don't see the new permissions (`Can change status to draft`, `Can change status to new`, etc)
-run a management command `syncww`:
-
-    $ ./manage.py syncww
-
-Running the example project
-==================================
-A working example of a django-werewolf app is available here: https://bitbucket.org/barseghyanartur/django-werewolf
-(see the `example` directory).
-
-1. Go to example/example directory
-
-    $ cd example/example
-
-2. Install requirements (in your virtual environment)
-
-    $ pip install -r ../requirements.txt
-
-3. Copy local_settings.example to local_settings.py
-
-    $ cp local_settings.example local_settings.py
-
-4. Create the database
-
-    $ ./manage.py syncdb
-
-5. Run the project
-
-    $ ./manage.py runserver
-
-License
-============
-GPL 2.0/LGPL 2.1
-
-Support
-============
-For any issues contact me at the e-mail given in the `Author` section.
-
-Author
-==================================
-Artur Barseghyan <artur.barseghyan@gmail.com>
 from setuptools import setup, find_packages
 
 try:
-    readme = open(os.path.join(os.path.dirname(__file__), 'readme.rst')).read()
+    readme = open(os.path.join(os.path.dirname(__file__), 'README.rst')).read()
 except:
     readme = ''
 
-version = '0.1'
+version = '0.2'
 
 setup(
-    name='django-werewolf',
-    version=version,
-    description=("Item publishing workflow for Django."),
-    long_description=readme,
-    classifiers=[
-        'Programming Language :: Python',
-        'Intended Audience :: Developers',
-        'Operating System :: OS Independent',
+    name = 'django-werewolf',
+    version = version,
+    description = ("Item publishing workflow for Django."),
+    long_description = readme,
+    classifiers = [
+        "Programming Language :: Python",
+        "Programming Language :: Python :: 2.7",
+        "Programming Language :: Python :: 3",
+        "Programming Language :: Python :: 3.3",
+        "Environment :: Web Environment",
+        "Framework :: Django",
+        "Intended Audience :: Developers",
+        "Operating System :: OS Independent",
+        "Development Status :: 4 - Beta",
+        "License :: OSI Approved :: GNU General Public License v2 (GPLv2)",
+        "License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)",
     ],
-    keywords='workflow, publishing',
-    author='Artur Barseghyan',
-    author_email='artur.barseghyan@gmail.com',
-    url='https://bitbucket.org/barseghyanartur/django-werewolf',
-    package_dir={'':'src'},
-    packages=find_packages(where='./src'),
-    license='GPL 2.0/LGPL 2.1',
-    install_requires=['django-reversion==1.6.5']
+    keywords = 'workflow, publishing, django workflow',
+    author = 'Artur Barseghyan',
+    author_email = 'artur.barseghyan@gmail.com',
+    url = 'https://bitbucket.org/barseghyanartur/django-werewolf',
+    package_dir = {'':'src'},
+    packages = find_packages(where='./src'),
+    license = 'GPL 2.0/LGPL 2.1',
+    install_requires = [
+        'six==1.4.1',
+        #'django-reversion==1.6.5'
+        'django-reversion==1.7.1'
+    ]
 )

source_install.sh

+pip install -e hg+https://bitbucket.org/barseghyanartur/django-werewolf@stable#egg=django-werewolf

src/werewolf/triggers.py

         :return werewolf.triggers.WerewolfBaseTrigger: Subclass of ``werewolf.triggers.WerewolfBaseTrigger``.
         """
         key = self.__make_key(app_label, module_name, status)
-        if self._registry.has_key(key):
+        if key in self._registry:
             return self._registry[key]
 
     def get_for_model(self, model, status):

src/werewolf/utils.py

-__all__ = ('permission_key', 'permissions_for_base_model', 'status_choices_for_user', 'extend_werewolf_permissions')
+__all__ = ('permission_key', 'permissions_for_base_model', 'status_choices_for_user', \
+           'extend_werewolf_permissions')
 
 from django.utils.translation import ugettext_lazy as _
 
 
 CHOICES_KEYS = [choice[0] for choice in STATUS_CHOICES]
 
-
 def permission_key(status, choice_key):
     """
     Gets the permission key from ``choice_key`` given.
     """
     return '%s_%s' % (status, choice_key)
 
-
 def permissions_for_base_model(permissions=[]):
     """
     Gets/extends permissions for the base model based on the ``STATUS_CHOICES`` defined.
 
-    :param list|tuple permissions: Permissions you want to have in your model. Those permissions would be extended
-        by werewolf permissions.
+    :param list|tuple permissions: Permissions you want to have in your model. Those permissions would be
+        extended by werewolf permissions.
     :return list:
     """
     werewolf_permissions = []
     for choice_key in CHOICES_KEYS:
-        werewolf_permissions.append((permission_key(CHANGE_STATUS_TO, choice_key), _("Can change status to %s") % choice_key))
+        werewolf_permissions.append(
+            (permission_key(CHANGE_STATUS_TO, choice_key), _("Can change status to %s") % choice_key)
+            )
         # Not sure if this shall be taken out. This allows viewsing the status. Leave out for now.
         #permissions.append((permission_key(CAN_VIEW_STATUS, choice_key), _("Can view status %s") % choice_key))
 
 
     return werewolf_permissions
 
-
 def extend_werewolf_permissions(*args):
     """
     Extends model permissions with werewolf permissions.
     """
     return permissions_for_base_model(args)
 
-
 def status_choices_for_user(user, app_label):
     """
     Gets available status choices for the user given.
 
     :param django.contrib.auth.models.User user: User for who the permissions are checked.
     :param str module_name: `app_label` of the model to check permissions to.
-    :return list: List of choices in a same form as ``werewolf.defaults.STATUS_CHOICES`` but then limited to actual
-        choices that user has permissions to.
+    :return list: List of choices in a same form as ``werewolf.defaults.STATUS_CHOICES`` but then limited
+        to actual choices that user has permissions to.
     """
     statuses = []
     for choice_key in CHOICES_KEYS:
             statuses.append((choice_key, CHOICES[choice_key]))
 
     return statuses
-
-
-def trigger_import(app_label, module_name, status):
-    """
-    Dynamically imports the trigger class for the status change.
-
-    :deprecated: Use ``werewolf.triggers.registry.register`` instead.
-
-    :param str app_label:
-    :param str module_name:
-    :param str status:
-    :return werewolf.triggers.WerewolfBaseTrigger: Subclass of ``werewolf.triggers.WerewolfBaseTrigger``.
-    """
-    try:
-        exec "from %s.werewolf_triggers import Status%s%sTrigger as Trigger" % (app_label, module_name, status.title())
-        return Trigger
-    except:
-        pass
+./uninstall.sh
+./install.sh
+reset
+python example/example/manage.py test werewolf --traceback -v 3
+pip uninstall django-werewolf -y
+rm build -rf
+rm dist -rf
+rm src/django_werewolf.egg-info -rf