Skip to content

Concrete Classes

The ReflectionConcrete class is an advanced introspection utility designed to analyze concrete Python classes at runtime. It provides a comprehensive API for inspecting attributes, methods, properties, metadata, and dependencies of any concrete (non-abstract) class registered in the Orionis framework.

Unlike ReflectionAbstract, which operates on abstract base classes, ReflectionConcrete focuses exclusively on instantiable classes with complete implementations. This makes it the ideal tool for analyzing services, controllers, models, and any concrete framework component.

from orionis.services.introspection.concretes.reflection import ReflectionConcrete

The ReflectionConcrete class receives a valid concrete class as its parameter. If the provided class is abstract, a primitive type, a built-in, or not a class at all, a TypeError will be raised.

from orionis.services.introspection.concretes.reflection import ReflectionConcrete
class UserService:
"""Service for managing users."""
active: bool = True
def __init__(self, name: str = "default") -> None:
self.name = name
def greet(self) -> str:
return f"Hello, {self.name}"
reflection = ReflectionConcrete(UserService)

If you pass an invalid type:

from abc import ABC, abstractmethod
class MyContract(ABC):
@abstractmethod
def execute(self) -> str: ...
# TypeError: abstract class
ReflectionConcrete(MyContract)
# TypeError: not a class
ReflectionConcrete(42)
# TypeError: built-in
ReflectionConcrete(len)

The ReflectionConcrete class implements the IReflectionConcrete contract, which defines the complete interface for concrete class introspection:

from orionis.services.introspection.concretes.contracts.reflection import IReflectionConcrete

These methods provide basic identification information about the reflected class.

Returns the type (class) associated with the reflection instance.

cls = reflection.getClass()
# <class 'UserService'>

Returns the simple name of the class as a string.

name = reflection.getClassName()
# "UserService"

Returns the module name where the class is defined.

module = reflection.getModuleName()
# "app.services.user_service"

Returns the fully qualified name (module + class).

fqn = reflection.getModuleWithClassName()
# "app.services.user_service.UserService"

Returns the class docstring, or None if not defined.

doc = reflection.getDocstring()
# "Service for managing users."

Returns the list of direct base classes in resolution order.

bases = reflection.getBaseClasses()
# [<class 'object'>]

Returns the source code of the entire class or a specific method. Returns None if the source is not available.

# Source code of the entire class
source = reflection.getSourceCode()
# Source code of a specific method
method_source = reflection.getSourceCode("greet")

For private methods with name mangling, use the name without the prefix:

source = reflection.getSourceCode("__private_method")

Returns the absolute path of the file where the class is defined.

path = reflection.getFile()
# "/app/services/user_service.py"

Returns a dictionary with the class type annotations. Automatically resolves name mangling for private attributes.

annotations = reflection.getAnnotations()
# {"active": <class 'bool'>}

ReflectionConcrete classifies class attributes by visibility level, excluding methods, properties, staticmethod, and classmethod.

Returns all class attributes, combining public, protected, private, and dunder.

attrs = reflection.getAttributes()

Returns public attributes (no underscore prefix).

public = reflection.getPublicAttributes()
# {"active": True}

Returns protected attributes (_ prefix).

protected = reflection.getProtectedAttributes()
# {"_internal_flag": False}

Returns private attributes (__ prefix). Names are returned without name mangling.

private = reflection.getPrivateAttributes()
# {"__secret": "value"} — not "_ClassName__secret"

Returns custom dunder attributes of the class, excluding Python standard ones (__dict__, __module__, __doc__, etc.). getMagicAttributes is an alias for getDunderAttributes.

dunder = reflection.getDunderAttributes()
magic = reflection.getMagicAttributes() # Equivalent

Checks whether an attribute exists in the class.

reflection.hasAttribute("active") # True
reflection.hasAttribute("missing") # False

Gets the value of an attribute, with support for a default value.

value = reflection.getAttribute("active") # True
value = reflection.getAttribute("missing", "N/A") # "N/A"

Sets an attribute on the class. Only non-callable values are accepted; to add methods, use setMethod.

reflection.setAttribute("active", False) # True

Validations:

  • The name must be a valid Python identifier
  • Cannot be a reserved keyword
  • The value cannot be a callable (raises TypeError)

Removes an attribute from the class. Raises ValueError if the attribute does not exist.

reflection.removeAttribute("active") # True

ReflectionConcrete offers a granular API for inspecting methods organized along three axes: visibility (public, protected, private), type (instance, class, static, dunder), and nature (synchronous, asynchronous).

MethodDescription
getMethods()All methods (instance + class + static)
getPublicMethods()Public instance methods
getPublicSyncMethods()Public synchronous
getPublicAsyncMethods()Public asynchronous
getProtectedMethods()Protected instance methods (_)
getProtectedSyncMethods()Protected synchronous
getProtectedAsyncMethods()Protected asynchronous
getPrivateMethods()Private instance methods (__)
getPrivateSyncMethods()Private synchronous
getPrivateAsyncMethods()Private asynchronous
getPublicClassMethods()Public class methods
getPublicClassSyncMethods()Public synchronous class methods
getPublicClassAsyncMethods()Public asynchronous class methods
getProtectedClassMethods()Protected class methods
getProtectedClassSyncMethods()Protected synchronous class methods
getProtectedClassAsyncMethods()Protected asynchronous class methods
getPrivateClassMethods()Private class methods
getPrivateClassSyncMethods()Private synchronous class methods
getPrivateClassAsyncMethods()Private asynchronous class methods
getPublicStaticMethods()Public static methods
getPublicStaticSyncMethods()Public synchronous static methods
getPublicStaticAsyncMethods()Public asynchronous static methods
getProtectedStaticMethods()Protected static methods
getProtectedStaticSyncMethods()Protected synchronous static methods
getProtectedStaticAsyncMethods()Protected asynchronous static methods
getPrivateStaticMethods()Private static methods
getPrivateStaticSyncMethods()Private synchronous static methods
getPrivateStaticAsyncMethods()Private asynchronous static methods
getDunderMethods()Dunder methods (__init__, __repr__, etc.)
getMagicMethods()Alias for getDunderMethods()

All methods return list[str] with the names of the matching methods. Private method names are returned without name mangling.

class MyService:
def process(self) -> str:
return "done"
async def fetch(self) -> dict:
return {}
def _validate(self) -> bool:
return True
@classmethod
def create(cls) -> "MyService":
return cls()
@staticmethod
def version() -> str:
return "1.0"
reflection = ReflectionConcrete(MyService)
reflection.getPublicMethods() # ["process", "fetch"]
reflection.getPublicSyncMethods() # ["process"]
reflection.getPublicAsyncMethods() # ["fetch"]
reflection.getProtectedMethods() # ["_validate"]
reflection.getPublicClassMethods() # ["create"]
reflection.getPublicStaticMethods() # ["version"]

Checks whether a method exists in the class (searches across all categories).

reflection.hasMethod("process") # True
reflection.hasMethod("missing") # False

Adds a new method to the class. Raises ValueError if the name already exists or is invalid, and TypeError if the value is not callable.

def new_method(self) -> str:
return "new"
reflection.setMethod("new_method", new_method) # True

Removes a method from the class. Raises ValueError if the method does not exist.

reflection.removeMethod("new_method") # True

Returns the inspect.Signature object for a specific method.

sig = reflection.getMethodSignature("process")
# (self) -> str

Returns the names of all properties defined in the class.

class Config:
@property
def host(self) -> str:
"""Server hostname."""
return "localhost"
@property
def _port(self) -> int:
return 8080
reflection = ReflectionConcrete(Config)
reflection.getProperties() # ["host", "_port"]
MethodDescription
getPublicProperties()Public properties
getProtectedProperties()Protected properties (_)
getPrivateProperties()Private properties (__, without mangling)

Retrieves the value of a property by executing its getter. Raises ValueError if it does not exist, or TypeError if it is not a property.

value = reflection.getProperty("host") # "localhost"

Returns the signature of a property’s getter.

sig = reflection.getPropertySignature("host")
# (self) -> str

Returns the docstring of a property’s getter, or None if not defined.

doc = reflection.getPropertyDocstring("host")
# "Server hostname."

Returns the inspect.Signature object for the __init__ method.

sig = reflection.getConstructorSignature()
# (self, name: str = 'default') -> None

Analyzes the constructor dependencies, identifying resolved parameters (with default values or primitive types) and unresolved parameters (requiring dependency injection).

analysis = reflection.constructorSignature()
# Signature(resolved=[...], unresolved=[...])

Analyzes the dependencies of a specific method. Raises AttributeError if the method does not exist.

analysis = reflection.methodSignature("process")
# Signature(resolved=[...], unresolved=[...])

ReflectionConcrete implements an in-memory caching system that stores the results of introspection operations. This avoids recomputing expensive results on repeated calls.

The instance supports dictionary-style access for the cache:

# Check existence
"key" in reflection
# Get value (None if not found)
reflection["key"]
# Set value
reflection["key"] = value
# Delete entry
del reflection["key"]

Clears all cache entries. Subsequent method calls will recompute their results.

reflection.clearCache()