{ "info": { "author": "Robert Schindler", "author_email": "r.schindler@efficiosoft.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Framework :: Django", "Intended Audience :: Developers", "License :: OSI Approved :: GNU General Public License (GPL)", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "djexcept\n========\n\ndjexcept is a module that brings flexible exception handling to the\nDjango web framework.\n\nA weakness of the great Django web framework are its poor builtin error\nhandling capabilities. In plain Django, you can define custom error\nhandlers for 4 different exceptions (``SuspiciousOperation``,\n``PermissionDenied``, ``Http404`` and a fallback handler for runtime\nerrors which doesn't even get the exception passed to decide what to do\nbest).\n\nThat is where djexcept hooks in. For every type of exception you like -\neven custom ones - it lets you decide how to handle it. It provides a\ndefault exception handler that makes additional information about the\nexception available in a template context and then renders a template of\nyour choice. You can define the template to use, the HTTP status code to\nsend and even change the exception handler on a per exception basis.\nHowever, sensible defaults are provided for you to get up and running as\nquick as possible.\n\n**Note:** djexcept is still a young pice of software that I use in my\nDjango projects. There may be bugs I haven't found yet. However, the\ncodebase is reasonably small without lots of magic in it, hence things\nshouldn't go terribly wrong after all. Any bug reports and code review\nare highly appreciated.\n\nInstallation\n------------\n\nIt's as easy as this:\n\n::\n\n pip install djexcept\n\nCompatibility with Django versions\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\ndjexcept is tested to work with Django 1.10+, but it should also work\nwith earlier versions without problems. The contained middleware is\ncompatible with both the new ``MIDDLEWARE`` as well as the pre 1.10\n``MIDDLEWARE_CLASSES`` mechanism.\n\nGetting started\n---------------\n\n1. Add ``djexcept.middleware.ExceptionHandlingMiddleware`` to your\n ``MIDDLEWARE`` in ``settings.py``. No modification of\n ``INSTALLED_APPS`` is needed.\n\n2. Add the ``@djexcept.register()`` decorator to every custom exception\n you'd like to be handled by djexcept.\n\n ::\n\n import djexcept\n @djexcept.register()\n class MyCustomException(Exception):\n ...\n\n3. For exceptions you haven't defined yourself, you can call the\n ``register()`` function e.g. from inside your ``urls.py`` file like\n so:\n\n ::\n\n import djexcept\n djexcept.register(ValueError)\n\n4. Create a template called ``exception.html`` which might contain the\n following:\n\n ::\n\n

{{ exc_modname }}

\n

An exception of type {{ exc_name }} from {{ exc_module }} occured.

\n

Exception message: {{ exc }}

\n

The HTTP status code sent with this page is {{ status }}.

\n\n5. Raise an exception you have just registered from within your view and\n watch what happens.\n\nCustomization of exception handling\n-----------------------------------\n\nRegistration parameters\n~~~~~~~~~~~~~~~~~~~~~~~\n\nFor every type of exception you register, you may specify several\nparameters that influence how exceptions of that type are handled. The\nfollowing parameters may be passed to ``djexcept.register()`` as keyword\narguments:\n\n- ``handler``: exception handler (callable or string of type\n ``path.to.module.function``)\n- ``handle_subtypes``: boolean that controls whether **unregistered**\n subclasses of the exception class being registered should be handled\n in the same way as their ancestor\n\nAll other keyword arguments are passed through straight to the exception\nhandler. The following are those that the built-in exception handler\nunderstands:\n\n- ``template_name``: name of the template to use for rendering the\n error page\n- ``status``: HTTP status code for the error response\n- ``include_request`` whether to include the request in template\n context\n- ``context`` dictionary of which a copy is used as starting point for\n the template context; values in that context won't be overwritten\n\nIf some of these keyword arguments are not specified, default values for\nthem will automatically be inserted according to the ``DJEXCEPT_*``\nsettings (see below) before the handler is called.\n\nIt is at the sole discretion of the chosen exception handler to\ninterpret these keyword arguments as desired.\n\nThe built-in default exception handler\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\ndjexcept's built-in exception handler understands all of the keyword\narguments listed above and will create either a\n``django.template.response.SimpleTemplateResponse`` or a\n``django.template.response.TemplateResponse``, depending on the setting\nfor ``DJEXCEPT_INCLUDE_REQUEST``.\n\nIt uses ``djexcept.util.populate_context()`` to populate the context\nwith some handy values regarding the exception that you can use in your\ntemplate. Please see the API reference for details about these values.\n\nCustom exception handlers\n~~~~~~~~~~~~~~~~~~~~~~~~~\n\nThere is nothing stopping you from writing your own exception handler,\nas long as it follows some guidelines.\n\nAn exception handler has to be a callable that accepts as positional\narguments the request, the exception object and at least the keyword\narguments listed in the previous section, because these, if unspecified\nat time of registration, will be filled with default values. It must\nreturn either a ``django.http.response.HttpResponse`` object or\n``None``, in which case the exception isn't handled by djexcept and\nDjango's regular exception handling sets in.\n\nIf your custom handler doesn't care about some of the mandatory keyword\narguments, you could insert a ``**kwargs`` at the end of its argument\nlist to catch any extra keyword arguments and have it working even when\nnew ones are added to djexcept in the future.\n\n**Note:** Please keep in mind that exceptions raised from inside\nexception handlers are not handled by djexcept. to prevent creating an\ninfinite loop.\n\nHere is a simple example that populates the context with some value and\nthen calls djexcept's built-in handler to construct the response. Please\ndon't forget to create a copy of the context object before altering it,\nbecause dictionaries are mutable and you might otherwise change the\ncontext of subsequent exceptions.\n\n::\n\n import time\n from djexcept.handlers import handle_exception\n\n def my_exception_handler(request, exc, context=None, **kwargs):\n context = dict(context or {})\n context.setdefault(\"time\", time.ctime())\n return handle_exception(request, exc, context=context, **kwargs)\n\nHandling child exception types\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\ndjexcept has the ability to automatically handle any sub-type of a\nregistered exception type in the same way as their registered ancestor.\nThis behaviour is controlled by the ``DJEXCEPT_HANDLE_SUBTYPES`` setting\nand is enabled by default.\n\nIn practice, that allows you to write your own hirarchy of meaningful\nexception types that you can use within your view logic. Consider the\nfollowing example:\n\n::\n\n import djexcept\n\n @djexcept.register(template_name=\"exceptions/business_logic_violation.html\")\n class BusinessRuleViolation(Exception):\n pass\n\n class NegativeAccountBalance(BusinessRuleViolation):\n pass\n\n class OfferExpired(BusinessRuleViolation):\n pass\n\nUsing this example, raising either ``NegativeAccountBalance`` or\n``OfferExpired`` will be handled as it was a ``BusinessRuleViolation``,\nwhat it in fact is.\n\nIn your template, you could now introduce some conditional content:\n\n::\n\n {% if exc_name == \"NegativeAccountBalance\" %}\n ...\n {% elif exc_name == \"OfferExpired\" %}\n ...\n {% endif %}\n\nIn theory, you could even catch all possible sub-types of ``Exception``,\nhowever doing so is not recommended because it will hide potential bugs\nthat might occur at runtime:\n\n::\n\n import djexcept\n djexcept.register(Exception)\n\nSub-type handling can also be disabled per type by passing\n``handle_subtypes = False`` to ``djexcept.register()``.\n\nConfiguration\n-------------\n\ndjexcept introduces some new settings that may be used in\n``settings.py`` to customize its behaviour. Neither of them are required\nfor djexcept to work, because all have sensible default values that\nshould be just fine for most users.\n\n``DJEXCEPT_TEMPLATE_NAME``\n~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n(default: ``exception.html``)\n\nName of the default template to use.\n\n``DJEXCEPT_STATUS``\n~~~~~~~~~~~~~~~~~~~\n\n(default: ``400``)\n\nDefault HTTP status code for exception pages.\n\n``DJEXCEPT_EXCEPTION_HANDLER``\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n(default: ``djexcept.handlers.handle_exception``)\n\nDefault exception handler. Please specify it as a string of the form\n``path.to.module.function``, as known from Django's ``MIDDLEWARE`` list.\n\n``DJEXCEPT_HANDLE_SUBTYPES``\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n(default: ``True``)\n\nWhether to treat **unregistered** subclasses of registered exception\ntypes in the same way as their ancestor.\n\n``DJEXCEPT_INCLUDE_REQUEST``\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n(default: ``True``)\n\nWhether to include the ``request`` object into the template context.\n\n``DJEXCEPT_DISABLE_ON_DEBUG``\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n(default: ``False``)\n\nWhether to disable djexcept's exception handling when Django's debug\nmode is enabled. You might find this useful to see full tracebacks\ninstead of your custom exception pages while developing your project.\n\nAPI reference\n-------------\n\nRegistration\n~~~~~~~~~~~~\n\nThe public API methods of the ``djexcept.registration`` submodule are\nalso directly available in ``djexcept`` for convenience.\n\n``djexcept.register(exception_class, **attrs)``\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nRegisters the given Exception subclass for error handling with djexcept.\n\nThe additional keyword arguments are treated as follows: \\* ``handler``:\nan exception handler to overwrite the default one \\*\n``handle_subtypes``: may be used to overwrite the\n``DJEXCEPT_HANDLE_SUBTYPES`` setting on a per exception basis\n\nAll other keyword arguments are passed directly to the handler function\nwhen there is an exception to handle.\n\nThis function may also be used as a class decorator when defining custom\nexceptions.\n\n``djexcept.exceptions.RegistrationError`` is raised if the class was\nalready registered.\n\n``djexcept.unregister(exception_class)``\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nUnregisters the given exception class from djexcept.\n\n``djexcept.exceptions.RegistrationError`` is raised if the class wasn't\nregistered.\n\n``djexcept.is_registered(exception_class)``\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nChecks whether the given Exception subclass is registered for use with\ndjexcept.\n\n``djexcept.is_handled(exception_class)``\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nChecks whether the given exception class is handled by djexcept. If\n``DJEXCEPT_HANDLE_SUBTYPES`` setting is disabled and not overwritten at\nregistration stage, this function returns the same result as\n``djexcept.is_registered()``.\n\nHandlers\n~~~~~~~~\n\n``djexcept.handler.handle_exception(request, exc, template_name=None, status=None, include_request=None, context=None)``\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nThis is djexcept's default exception handler.\n\nIt uses ``djexcept.util.populate_context()`` to populate the context\nwith some handy values regarding the exception that you can use in your\ntemplate.\n\nA ``django.template.response.SimpleTemplateResponse`` or\n``django.template.response.TemplateResponse`` is returned.\n\nUtil\n~~~~\n\n``populate_context(context, exc, status=None)``\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nPopulates the given context dictionary with djexcept's handy default\nvalues. The dictionary is altered in-place, but values that are already\npresent won't be overwritten.\n\nThe following values are added to the context: \\* ``exc``: the exception\nobject \\* ``exc_name``: the name of the exception type (e.g.\n``PermissionDenied`` or ``ValueError``) \\* ``exc_module``: the module\nname of the exception's type (e.g. ``django.core.exceptions`` or\n``builtins``) \\* ``exc_modname``: both concatenated, separated by a\nperiod (e.g. ``django.core.exceptions.PermissionDenied`` or\n``builtins.ValueError``) \\* ``status``: the HTTP status code used (only\nadded if not ``None``)\n\nExceptions\n~~~~~~~~~~\n\n``djexcept.exceptions.ImproperlyConfigured``\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nIs raised when something went wrong at settings parsing.\n\n``djexcept.exceptions.RegistrationError``\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nIs raised when an illegal call to ``djexcept.register()`` or\n``djexcept.unregister()`` is made.\n\nContributing\n------------\n\nContributions are always welcome. Please use issues and pull requests on\nGitHub.\n", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/efficiosoft/djexcept", "keywords": "", "license": "GPL-3", "maintainer": "", "maintainer_email": "", "name": "djexcept", "package_url": "https://pypi.org/project/djexcept/", "platform": "", "project_url": "https://pypi.org/project/djexcept/", "project_urls": { "Homepage": "https://github.com/efficiosoft/djexcept" }, "release_url": "https://pypi.org/project/djexcept/0.1.3/", "requires_dist": null, "requires_python": "", "summary": "Flexible and versatile exception handling for django.", "version": "0.1.3" }, "last_serial": 3114316, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "3e0ad1af49e7aa5562b8c3d87f987401", "sha256": "553e57dabbb0dc24297f4abc3f8749ea544d3386b62f96617d9574cfcc7510b2" }, "downloads": -1, "filename": "djexcept-0.1.0.tar.gz", "has_sig": false, "md5_digest": "3e0ad1af49e7aa5562b8c3d87f987401", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18188, "upload_time": "2017-08-21T17:38:46", "url": "https://files.pythonhosted.org/packages/02/a0/17e83e8f9980b04f2c2a169c990dbadd2b505d1a0f472a803dedf51678d9/djexcept-0.1.0.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "e1cab92fd35153c94737c6271f442e9d", "sha256": "eecc88e7a2e7ca53c135cb33a8fb1b75935f1a525af8e0741e4fada1e8a05f02" }, "downloads": -1, "filename": "djexcept-0.1.1.tar.gz", "has_sig": false, "md5_digest": "e1cab92fd35153c94737c6271f442e9d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18543, "upload_time": "2017-08-21T18:43:41", "url": "https://files.pythonhosted.org/packages/bf/22/498d74189da249e76ef9123929d4987178b0e5047cf0d9e8d6265e803b7d/djexcept-0.1.1.tar.gz" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "39fb0258ef4e868f39b667e3e7120dd2", "sha256": "51d596c56b702257832678e9f107b4e092ea0afa473bf30b8d4db168b8d7115d" }, "downloads": -1, "filename": "djexcept-0.1.2.tar.gz", "has_sig": false, "md5_digest": "39fb0258ef4e868f39b667e3e7120dd2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18566, "upload_time": "2017-08-21T19:05:19", "url": "https://files.pythonhosted.org/packages/50/7b/7a64799ee761787852ad1d0f7ec13a2af8e090a186c431584f30647f82d3/djexcept-0.1.2.tar.gz" } ], "0.1.3": [ { "comment_text": "", "digests": { "md5": "a7e0ee139b6b7fc5df02e700da895269", "sha256": "ba7cf4e30ae290109cf9a4f696635e6114be568c4bbb924c6c51203bd8662cdb" }, "downloads": -1, "filename": "djexcept-0.1.3.tar.gz", "has_sig": false, "md5_digest": "a7e0ee139b6b7fc5df02e700da895269", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20299, "upload_time": "2017-08-22T10:33:01", "url": "https://files.pythonhosted.org/packages/c6/6d/15cdaf0781d9c30f3e5831ccb9696d5c5f7339abad729d611a7138108185/djexcept-0.1.3.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "a7e0ee139b6b7fc5df02e700da895269", "sha256": "ba7cf4e30ae290109cf9a4f696635e6114be568c4bbb924c6c51203bd8662cdb" }, "downloads": -1, "filename": "djexcept-0.1.3.tar.gz", "has_sig": false, "md5_digest": "a7e0ee139b6b7fc5df02e700da895269", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20299, "upload_time": "2017-08-22T10:33:01", "url": "https://files.pythonhosted.org/packages/c6/6d/15cdaf0781d9c30f3e5831ccb9696d5c5f7339abad729d611a7138108185/djexcept-0.1.3.tar.gz" } ] }