Lasse Schuirmann Lasse Schuirmann - 1 month ago 13
Python Question

Get Outer Class Name for Nested Class (Python)

Background



(Might be relevant because there might be a simpler way to achieve what I want.)

I want to build a declarative way to define "aspects" that can be analyzed by a static code analysis tool. The whole concept is written down here. Every aspect (say
Redundancy
) may have sub aspects recursively (say
Redundancy.Clone
) and every aspect shall have documentation and arbitrary other properties. The user shall be able to choose which aspects to analyze and I have to programmatically find out for the internal representation of an aspect if it's the one choosen by the user (i.e. for a given class
Redundancy.Clone
I want to validate that it belongs to a given string
redundancy.clone
but not
redundancy.unused_import
).

I decided to use classes like this:

class Redundancy(Aspect):
"""
This meta aspect describes any kind of redundancy in your source code.
"""

# Can't inherit from Redundancy here because of the recursion
class Clone(Aspect):
"""
This redundancy describes a code clone. Code clones are different pieces of
code in your codebase that are very similar.
"""

# Stuff...


Problem



For a given
Aspect
class I want to get the describing string (
Redundancy.Clone
->
redundancy.clone
). For that I have to get the name of the surrounding module/class/whatever it is, check if it's a class (trivial) and construct a string out of it.

Possible Solutions and How They Failed



I did try looking at the
dir
of my classes to see if there's anything useful in the dunder methods I could use but found nothing except the
repr
which in the above case is
<class 'coalib.bearlib.aspects.Redundancy.Clone'>
when living in the
aspects
module. This shows that it should be possible but I have no idea on how
repr
gets this information and I would like to avoid using
repr
and stripping off the unneeded stuff as that's kind of a hack.

I am not able to inherit the nested class from the outer one as it is not completely defined yet. I want them nested for the usability, being able to
from ... import Redundancy
and in my source code write
Redundancy.Clone
is a huge plus.

Any suggestions, including changing my approach, would be appreciated.

DJV DJV
Answer

You could use __qualname__ (PEP 3155)

>>> class C:
...   def f(): pass
...   class D:
...     def g(): pass
...
>>> C.__qualname__
'C'
>>> C.f.__qualname__
'C.f'
>>> C.D.__qualname__
'C.D'
>>> C.D.g.__qualname__
'C.D.g'
Comments