X-Git-Url: https://git.mdrn.pl/django-ssify.git/blobdiff_plain/3d2c8ba4dfb4774daff367dae1656099eb2b562c..196df9e8170262c31790260d4e280b9981b557d1:/ssify/exceptions.py?ds=sidebyside diff --git a/ssify/exceptions.py b/ssify/exceptions.py index 8acc55c..d9e5319 100644 --- a/ssify/exceptions.py +++ b/ssify/exceptions.py @@ -1,68 +1,98 @@ -class SsifyError(BaseException): +# -*- coding: utf-8 -*- +# This file is part of django-ssify, licensed under GNU Affero GPLv3 or later. +# Copyright © Fundacja Nowoczesna Polska. See README.md for more information. +# +""" +Exception classes used in django-ssify. +""" +from __future__ import unicode_literals +from django.utils.encoding import python_2_unicode_compatible + + +class RequestMixin(object): + """Lets us print request and view data in the exceptions messages.""" + + def __init__(self, request, *args): + self.request = request + super(RequestMixin, self).__init__(*args) + + def view_path(self): + """Returns full Python path to the view used in the request.""" + try: + view = self.request.resolver_match.func + return "%s.%s" % (view.__module__, view.__name__) + except AttributeError: + return "" + + +class SsifyError(RequestMixin, BaseException): + """Base class for all the errors.""" pass -class SsifyWarning(Warning): +class SsifyWarning(RequestMixin, Warning): + """Base class for all the warnings.""" pass +@python_2_unicode_compatible class UndeclaredSsiVarsError(SsifyError): + """An ssi_included view used a SSI variable, but didn't declare it.""" + def __init__(self, request, ssi_vars): super(UndeclaredSsiVarsError, self).__init__(request, ssi_vars) def __str__(self): - request = self.args[0] - view = request.resolver_match.func - return "The view '%s.%s' at '%s' is marked as `ssi_included`, "\ + return "The view '%s' at '%s' is marked as `ssi_included`, "\ "but it uses ssi variables not declared in `get_ssi_vars` "\ "argument: %s. " % ( - view.__module__, view.__name__, request.path, - repr(self.args[1])) + self.view_path(), self.request.get_full_path(), + repr(self.args[0])) +@python_2_unicode_compatible class UnusedSsiVarsWarning(SsifyWarning): + """An ssi_included declared a SSI variable, but didn't use it.""" + def __init__(self, request, ssi_vars): super(UnusedSsiVarsWarning, self).__init__(request, ssi_vars) def __str__(self): - request = self.args[0] - view = request.resolver_match.func - return "The `ssi_included` view '%s.%s' at '%s' declares "\ + return "The `ssi_included` view '%s' at '%s' declares "\ "using SSI variables %s but it looks like they're not "\ "really used. " % ( - view.__module__, view.__name__, request.path, self.args[1]) - - -class UndeclaredSsiRefError(SsifyError): - def __init__(self, request, var, ref_name): - super(UndeclaredSsiRefError, self).__init__(request, var, ref_name) - - def __str__(self): - request = self.args[0] - view = request.resolver_match.func - return "Error while rendering ssi_included view '%s.%s' at '%s': "\ - "SSI variable %s references variable %s, which doesn't match "\ - "any variable declared in `get_ssi_vars`. " % ( - view.__module__, view.__name__, request.path, - repr(self.args[1]), self.args[2]) + self.view_path(), self.request.get_full_path(), + self.args[0]) +@python_2_unicode_compatible class NoLangFieldError(SsifyError): + """ssi_included views should have a `lang` field in their URL patterns.""" + def __init__(self, request): super(NoLangFieldError, self).__init__(request) def __str__(self): - request = self.args[0] - view = request.resolver_match.func - return "The view '%s.%s' at '%s' is marked as `ssi_included` "\ + return "The view '%s' at '%s' is marked as `ssi_included` "\ "with use_lang=True, but its URL match doesn't provide "\ "a 'lang' keyword argument for language. " % ( - view.__module__, view.__name__, request.path) + self.view_path(), self.request.get_full_path()) +@python_2_unicode_compatible class SsiVarsDependencyCycleError(SsifyError): - def __init__(self, ssi_vars): - super(SsiVarsDependencyCycleError, self).__init__(ssi_vars) + """Looks like there's a dependency cycle in the SSI variables. + + Yet to find an example of a configuration that triggers that. + """ + + def __init__(self, request, ssi_vars, resolved): + super(SsiVarsDependencyCycleError, self).__init__( + request, ssi_vars, resolved) def __str__(self): - return "Dependency cycle in SSI variables: %s." % self.args[0] + return "The view '%s' at '%s' has dependency cycle. "\ + "Unresolved SSI variables:\n%s\n\n"\ + "Resolved SSI variables:\n%s." % ( + self.view_path(), self.request.get_full_path(), + self.args[0], self.args[1])