How to get outer class name from an inner class?

J

John Gordon

I'm trying to come up with a scheme for organizing exceptions in
my application.

Currently, I'm using a base class which knows how to look up the text
of a specific error in a database table, keyed on the error class name.

The base class looks like this:

class ApplicationException(Exception):
"""Base class for application-specific errors."""

def get_message(self):
"""Return the error message associated with this class name."""

class_name = self.__class__.__name__
return UserMessage.objects.get(key=class_name).text

And then I define a bunch of subclasses which all have different names:

class QuestionTooShortError(NetIDAppsError):
"""User entered a security question which is too short."""
pass

class QuestionTooLongError(NetIDAppsError):
"""User entered a security question which is too long."""
pass

This scheme works, but I'd like to make it more streamlined. Specifically,
I'd like to group the classes underneath a parent class, like so:

class Question(ApplicationException):

class TooShort(ApplicationException):
pass

class TooLong(ApplicationException):
pass

This will make it easier in the future for organizing lots of sub-errors.

My problem is this: the get_message() method in the base class only knows
the current class name, i.e. "TooShort" or "TooLong". But that's not
enough; I also need to know the outer class name, i.e. "Question.TooShort"
or "Question.TooLong". How do I get the outer class name?

Thanks,
 
J

John Gordon

In said:
class QuestionTooShortError(NetIDAppsError):
"""User entered a security question which is too short."""
pass
class QuestionTooLongError(NetIDAppsError):
"""User entered a security question which is too long."""
pass

Oops! These classes inherit from ApplicationException, not NetIDAppsError.
 
S

Steve Howell

I'm trying to come up with a scheme for organizing exceptions in
my application.

Currently, I'm using a base class which knows how to look up the text
of a specific error in a database table, keyed on the error class name.

The base class looks like this:

class ApplicationException(Exception):
    """Base class for application-specific errors."""

    def get_message(self):
        """Return the error message associated with this class name."""

        class_name = self.__class__.__name__
        return UserMessage.objects.get(key=class_name).text

And then I define a bunch of subclasses which all have different names:

class QuestionTooShortError(NetIDAppsError):
    """User entered a security question which is too short."""
    pass

class QuestionTooLongError(NetIDAppsError):
    """User entered a security question which is too long."""
    pass

This scheme works, but I'd like to make it more streamlined.  Specifically,
I'd like to group the classes underneath a parent class, like so:

class Question(ApplicationException):

    class TooShort(ApplicationException):
        pass

    class TooLong(ApplicationException):
        pass

This will make it easier in the future for organizing lots of sub-errors.

My problem is this: the get_message() method in the base class only knows
the current class name, i.e. "TooShort" or "TooLong".  But that's not
enough; I also need to know the outer class name, i.e. "Question.TooShort"
or "Question.TooLong".  How do I get the outer class name?

This may be somewhat relevant to you, although it doesn't specifically
answer your question for pre-3.3:

http://www.python.org/dev/peps/pep-3155/ (Qualified name for classes
and functions)
 
A

alex23

I'd like to group the classes underneath a parent class, like so:

class Question(ApplicationException):

    class TooShort(ApplicationException):
        pass

    class TooLong(ApplicationException):
        pass

This will make it easier in the future for organizing lots of sub-errors.

My problem is this: the get_message() method in the base class only knows
the current class name, i.e. "TooShort" or "TooLong".  But that's not
enough; I also need to know the outer class name, i.e. "Question.TooShort"
or "Question.TooLong".  How do I get the outer class name?

This might do the trick:

import inspect

def exception_members(scope):
classes = (m[1] for m in inspect.getmembers(scope,
inspect.isclass))
return set(
c for c in classes if Exception in c.__mro__
)

class ApplicationException(Exception):
@property
def outer_scope(self):
for _class in
exception_members(inspect.getmodule(self.__class__)):
if self.__class__ in exception_members(_class):
return _class

def get_message(self):
scope = self.outer_scope
class_name = scope.__name__ + '.' if scope else ''
class_name += self.__class__.__name__
return class_name

When get_message is run, it looks in the module where the exception
was defined for any new classes derived from Exception, then looks at
the members of each of those to see if it matches the current object's
class.

Not really well tested, so beware :)
 
U

Ulrich Eckhardt

Am 08.05.2012 22:05, schrieb John Gordon:
[...]
class QuestionTooShortError(ApplicationException):
"""User entered a security question which is too short."""
pass

class QuestionTooLongError(ApplicationException):
"""User entered a security question which is too long."""
pass

This scheme works, but I'd like to make it more streamlined. Specifically,
I'd like to group the classes underneath a parent class, like so:

class Question(ApplicationException):

class TooShort(ApplicationException):
pass

class TooLong(ApplicationException):
pass

This will make it easier in the future for organizing lots of sub-errors.

What is it that this "parent class" represents? What is the relation
between class Question and class TooShort? In general terms, it isn't
even a parent class but just an outer class, a parent class implies that
child classes inherit from it.

I think that you're going about this the wrong way, and that a module
represents much better what you are trying to express here. Your code
actually looks a bit like it was written with a strong Java or C++
background, could that be the case?

My problem is this: the get_message() method in the base class only knows
the current class name, i.e. "TooShort" or "TooLong". But that's not
enough; I also need to know the outer class name, i.e. "Question.TooShort"
or "Question.TooLong". How do I get the outer class name?

# in module "Question"
class _Exception(ApplicationException):
def get_message(self):
return self._lookup_message("Question." +
self.__class__.__name__)
class TooLong(_Exception):
pass


You might even be able to look up the module name instead of hard-coding
it in one place.

Uli
 
A

Adam Skutt

I'm trying to come up with a scheme for organizing exceptions in
my application.

Currently, I'm using a base class which knows how to look up the text
of a specific error in a database table, keyed on the error class name.

The base class looks like this:

class ApplicationException(Exception):
    """Base class for application-specific errors."""

    def get_message(self):
        """Return the error message associated with this class name."""

        class_name = self.__class__.__name__
        return UserMessage.objects.get(key=class_name).text

And then I define a bunch of subclasses which all have different names:

class QuestionTooShortError(NetIDAppsError):
    """User entered a security question which is too short."""
    pass

class QuestionTooLongError(NetIDAppsError):
    """User entered a security question which is too long."""
    pass

This scheme works, but I'd like to make it more streamlined.  Specifically,
I'd like to group the classes underneath a parent class, like so:

class Question(ApplicationException):

    class TooShort(ApplicationException):
        pass

    class TooLong(ApplicationException):
        pass

This will make it easier in the future for organizing lots of sub-errors.

It's no more or less organized than using a module, so use a module.
This is why they exist, after all.

That being said, this seems like a bad idea to me: this is a lot of
code and types just for a message lookup! Exception types should
usually be created based on what you expect users to catch, not based
on what you could throw. If all of these exceptions will be handled
in the same way, then they shouldn't be distinct types.

Adam
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top