Ir al contenido

Clases Abstractas

La clase ReflectionAbstract es una utilidad avanzada de introspección diseñada para analizar clases base abstractas (ABC) de Python en tiempo de ejecución. Proporciona una API completa para inspeccionar atributos, métodos, propiedades, metadatos y dependencias de cualquier clase abstracta registrada en el framework Orionis.

Esta herramienta es especialmente útil para construir sistemas de inyección de dependencias, generar documentación automática, validar contratos de interfaces y realizar análisis estático en tiempo de ejecución.

from orionis.services.introspection.abstract.reflection import ReflectionAbstract

La clase ReflectionAbstract recibe como parámetro una clase abstracta válida que herede de abc.ABC. Si la clase proporcionada no es abstracta, se lanzará un TypeError.

from abc import ABC, abstractmethod
from orionis.services.introspection.abstract.reflection import ReflectionAbstract
class MyContract(ABC):
@abstractmethod
def execute(self) -> str:
"""Execute the operation."""
...
reflection = ReflectionAbstract(MyContract)

Si intentas pasar una clase que no es abstracta:

class RegularClass:
pass
# Esto lanzará TypeError:
# "The class 'RegularClass' is not an abstract base class."
reflection = ReflectionAbstract(RegularClass)

La clase ReflectionAbstract implementa el contrato IReflectionAbstract, que define la interfaz completa para la introspección de clases abstractas:

from orionis.services.introspection.abstract.contracts.reflection import IReflectionAbstract

Estos métodos permiten obtener información básica de identificación sobre la clase abstracta reflejada.

Retorna el tipo (la clase) asociado a la instancia de reflexión.

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

Retorna el nombre de la clase abstracta como cadena de texto.

name = reflection.getClassName()
# "MyContract"

Retorna el nombre completo del módulo donde está definida la clase.

module = reflection.getModuleName()
# "app.contracts.my_contract"

Retorna la ruta completa del módulo junto con el nombre de la clase, separados por un punto.

full_name = reflection.getModuleWithClassName()
# "app.contracts.my_contract.MyContract"

Estos métodos extraen información descriptiva sobre la clase abstracta.

Retorna el docstring de la clase, o None si no tiene uno definido.

doc = reflection.getDocstring()
# "Execute the operation." o None

Retorna una lista con las clases base directas de la clase abstracta.

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

Recupera el código fuente completo de la clase como cadena de texto. Lanza ValueError si no se puede obtener.

source = reflection.getSourceCode()

Retorna la ruta absoluta del archivo donde está definida la clase. Lanza ValueError si no se puede determinar.

file_path = reflection.getFile()
# "/path/to/app/contracts/my_contract.py"

Retorna un diccionario con las anotaciones de tipo de los atributos de la clase. Los nombres de atributos privados se normalizan eliminando el prefijo de name mangling.

from abc import ABC, abstractmethod
class Configurable(ABC):
name: str
__timeout: int
@abstractmethod
def configure(self) -> None:
...
reflection = ReflectionAbstract(Configurable)
annotations = reflection.getAnnotations()
# {"name": <class 'str'>, "__timeout": <class 'int'>}

La clase proporciona un conjunto completo de métodos para inspeccionar y manipular atributos a nivel de clase, organizados por nivel de visibilidad.

Verifica si la clase tiene un atributo específico.

exists = reflection.hasAttribute("my_attr")
# True o False

Obtiene el valor de un atributo de clase. Retorna None si el atributo no existe.

value = reflection.getAttribute("my_attr")

Establece el valor de un atributo en la clase. El nombre debe ser un identificador Python válido y no puede ser una palabra reservada. El valor no puede ser callable.

reflection.setAttribute("max_retries", 3)
# True

Elimina un atributo de la clase. Lanza ValueError si el atributo no existe.

reflection.removeAttribute("max_retries")
# True

Retorna un diccionario con todos los atributos a nivel de clase, combinando atributos públicos, protegidos, privados y dunder. Excluye callables, métodos estáticos/de clase y propiedades.

all_attrs = reflection.getAttributes()
# {"public_attr": 1, "_protected": 2, "__private": 3, "__custom__": 4}

Retorna solo los atributos públicos (sin prefijo de guion bajo).

public = reflection.getPublicAttributes()
# {"public_attr": 1}

Retorna los atributos protegidos (un guion bajo inicial, sin ser dunder ni privado).

protected = reflection.getProtectedAttributes()
# {"_protected": 2}

Retorna los atributos privados (con name mangling). Los nombres se normalizan eliminando el prefijo _ClassName.

private = reflection.getPrivateAttributes()
# {"__private": 3}

Retorna los atributos dunder personalizados (doble guion bajo al inicio y al final). Excluye automáticamente los atributos dunder incorporados de Python como __class__, __dict__, __module__, etc.

dunder = reflection.getDunderAttributes()
# {"__custom__": 4}

Alias de getDunderAttributes(). Retorna los mismos atributos mágicos.

magic = reflection.getMagicAttributes()

La API de introspección de métodos es una de las características más completas de ReflectionAbstract. Permite consultar métodos organizados por visibilidad (público, protegido, privado), tipo (instancia, clase, estático) y naturaleza (síncrono, asíncrono).

Verifica si la clase contiene un método con el nombre dado.

exists = reflection.hasMethod("execute")
# True o False

Elimina un método de la clase abstracta. Lanza ValueError si el método no existe.

reflection.removeMethod("execute")
# True

Recupera la firma (inspect.Signature) de un método específico. Lanza ValueError si el método no existe o no es callable.

import inspect
sig = reflection.getMethodSignature("execute")
# <Signature (self) -> str>

Retorna una lista con los nombres de todos los métodos definidos en la clase, incluyendo públicos, protegidos, privados, de clase y estáticos.

all_methods = reflection.getMethods()
# ["execute", "validate", "_prepare", "__internal", "from_config", ...]

Retorna los nombres de todos los métodos de instancia públicos. Excluye dunder, protegidos, privados, estáticos, de clase y propiedades.

public = reflection.getPublicMethods()
# ["execute", "validate"]

Retorna solo los métodos públicos síncronos (no son coroutines).

sync = reflection.getPublicSyncMethods()

Retorna solo los métodos públicos asíncronos (funciones coroutine).

async_methods = reflection.getPublicAsyncMethods()

Retorna los métodos de instancia protegidos (un guion bajo inicial).

protected = reflection.getProtectedMethods()
# ["_prepare", "_validate_input"]

Retorna los métodos protegidos síncronos.

sync = reflection.getProtectedSyncMethods()

Retorna los métodos protegidos asíncronos.

async_methods = reflection.getProtectedAsyncMethods()

Retorna los métodos de instancia privados (con name mangling). Los nombres se normalizan eliminando el prefijo _ClassName.

private = reflection.getPrivateMethods()
# ["__internal_process"]

Retorna los métodos privados síncronos.

sync = reflection.getPrivateSyncMethods()

Retorna los métodos privados asíncronos.

async_methods = reflection.getPrivateAsyncMethods()

Retorna los métodos de clase públicos (decorados con @classmethod).

class_methods = reflection.getPublicClassMethods()
# ["from_config"]

Retorna los métodos de clase públicos síncronos.

sync = reflection.getPublicClassSyncMethods()

Retorna los métodos de clase públicos asíncronos.

async_methods = reflection.getPublicClassAsyncMethods()

Retorna los métodos de clase protegidos.

protected = reflection.getProtectedClassMethods()

Retorna los métodos de clase protegidos síncronos.

sync = reflection.getProtectedClassSyncMethods()

Retorna los métodos de clase protegidos asíncronos.

async_methods = reflection.getProtectedClassAsyncMethods()

Retorna los métodos de clase privados. Los nombres se normalizan eliminando el prefijo de name mangling.

private = reflection.getPrivateClassMethods()

Retorna los métodos de clase privados síncronos.

sync = reflection.getPrivateClassSyncMethods()

Retorna los métodos de clase privados asíncronos.

async_methods = reflection.getPrivateClassAsyncMethods()

Retorna los métodos estáticos públicos (decorados con @staticmethod).

static_methods = reflection.getPublicStaticMethods()
# ["utility_method"]

Retorna los métodos estáticos públicos síncronos.

sync = reflection.getPublicStaticSyncMethods()

Retorna los métodos estáticos públicos asíncronos.

async_methods = reflection.getPublicStaticAsyncMethods()

Retorna los métodos estáticos protegidos.

protected = reflection.getProtectedStaticMethods()

Retorna los métodos estáticos protegidos síncronos.

sync = reflection.getProtectedStaticSyncMethods()

Retorna los métodos estáticos protegidos asíncronos.

async_methods = reflection.getProtectedStaticAsyncMethods()

Retorna los métodos estáticos privados. Los nombres se normalizan eliminando el prefijo de name mangling.

private = reflection.getPrivateStaticMethods()

Retorna los métodos estáticos privados síncronos.

sync = reflection.getPrivateStaticSyncMethods()

Retorna los métodos estáticos privados asíncronos.

async_methods = reflection.getPrivateStaticAsyncMethods()

Retorna todos los métodos dunder (doble guion bajo al inicio y al final) definidos en la clase. Excluye métodos estáticos, de clase y propiedades.

dunder = reflection.getDunderMethods()
# ["__init__", "__str__", "__repr__"]

Alias de getDunderMethods().

magic = reflection.getMagicMethods()

Métodos para inspeccionar las propiedades (decoradas con @property) definidas en la clase abstracta.

Retorna una lista con los nombres de todas las propiedades. Los nombres de propiedades privadas se normalizan eliminando el prefijo de name mangling.

props = reflection.getProperties()
# ["name", "_status", "__secret"]

Retorna las propiedades públicas (sin prefijo de guion bajo).

public = reflection.getPublicProperties()
# ["name"]

Retorna las propiedades protegidas (un guion bajo inicial).

protected = reflection.getProtectedProperties()
# ["_status"]

Retorna las propiedades privadas. Los nombres se normalizan eliminando el prefijo _ClassName.

private = reflection.getPrivateProperties()
# ["__secret"]

Recupera la firma del método getter de una propiedad. Lanza ValueError si la propiedad no existe.

sig = reflection.getPropertySignature("name")
# <Signature (self) -> str>

Recupera el docstring del método getter de una propiedad. Retorna None si no tiene docstring.

doc = reflection.getPropertyDocstring("name")
# "The name of the entity." o None

Estos métodos analizan las firmas de constructores y métodos para determinar sus dependencias, lo cual es fundamental para los sistemas de inyección de dependencias del framework.

Retorna un objeto Signature que contiene las dependencias del constructor, incluyendo dependencias resueltas (con tipo anotado) y no resueltas (parámetros sin anotación ni valor por defecto).

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

Retorna un objeto Signature con las dependencias de un método específico. Lanza AttributeError si el método no existe.

sig = reflection.methodSignature("execute")
# Signature(resolved=[...], unresolved=[...])

ReflectionAbstract implementa un sistema de caché interno para optimizar el rendimiento. Los resultados de las operaciones de introspección se almacenan automáticamente y se reutilizan en llamadas posteriores.

La clase implementa los métodos especiales __getitem__, __setitem__, __contains__ y __delitem__, lo que permite interactuar con la caché como si fuera un diccionario:

# Verificar si existe una clave en caché
"source_code" in reflection
# Obtener un valor cacheado
value = reflection["source_code"]
# Establecer un valor en caché
reflection["custom_key"] = "custom_value"
# Eliminar una entrada de caché
del reflection["custom_key"]

Limpia toda la caché de reflexión, forzando que las llamadas posteriores recalculen los resultados.

reflection.clearCache()
from abc import ABC, abstractmethod
from orionis.services.introspection.abstract.reflection import ReflectionAbstract
class PaymentGateway(ABC):
"""Abstract payment gateway interface."""
gateway_name: str
_timeout: int = 30
__retries: int = 3
@abstractmethod
def process_payment(self, amount: float, currency: str) -> bool:
"""Process a payment transaction."""
...
@abstractmethod
async def refund(self, transaction_id: str) -> bool:
"""Refund a transaction."""
...
@classmethod
def from_config(cls, config: dict) -> 'PaymentGateway':
...
@staticmethod
def supported_currencies() -> list:
...
@property
def name(self) -> str:
"""The gateway display name."""
...
# Crear instancia de reflexión
reflection = ReflectionAbstract(PaymentGateway)
# Identidad
print(reflection.getClassName())
# "PaymentGateway"
# Metadatos
print(reflection.getDocstring())
# "Abstract payment gateway interface."
print(reflection.getBaseClasses())
# [<class 'abc.ABC'>]
# Atributos por visibilidad
print(reflection.getPublicAttributes())
# {"gateway_name": <class 'str'>} o atributos con valor asignado
print(reflection.getProtectedAttributes())
# {"_timeout": 30}
print(reflection.getPrivateAttributes())
# {"__retries": 3}
# Métodos
print(reflection.getPublicMethods())
# ["process_payment", "refund"]
print(reflection.getPublicSyncMethods())
# ["process_payment"]
print(reflection.getPublicAsyncMethods())
# ["refund"]
print(reflection.getPublicClassMethods())
# ["from_config"]
print(reflection.getPublicStaticMethods())
# ["supported_currencies"]
# Propiedades
print(reflection.getPublicProperties())
# ["name"]
print(reflection.getPropertyDocstring("name"))
# "The gateway display name."
# Dependencias del método
sig = reflection.methodSignature("process_payment")
print(sig)
MétodoRetornoDescripción
getClass()typeRetorna la clase abstracta reflejada
getClassName()strNombre de la clase
getModuleName()strMódulo donde está definida
getModuleWithClassName()strRuta completa modulo.Clase
getDocstring()str | NoneDocstring de la clase
getBaseClasses()list[type]Clases base directas
getSourceCode()strCódigo fuente completo
getFile()strRuta absoluta del archivo
getAnnotations()dictAnotaciones de tipo
hasAttribute(name)boolVerifica existencia de atributo
getAttribute(name)object | NoneValor del atributo
setAttribute(name, value)boolEstablece un atributo
removeAttribute(name)boolElimina un atributo
getAttributes()dictTodos los atributos
getPublicAttributes()dictAtributos públicos
getProtectedAttributes()dictAtributos protegidos
getPrivateAttributes()dictAtributos privados
getDunderAttributes()dictAtributos dunder
getMagicAttributes()dictAlias de getDunderAttributes
hasMethod(name)boolVerifica existencia de método
removeMethod(name)boolElimina un método
getMethodSignature(name)SignatureFirma del método
getMethods()list[str]Todos los métodos
getPublicMethods()list[str]Métodos públicos
getPublicSyncMethods()list[str]Métodos públicos síncronos
getPublicAsyncMethods()list[str]Métodos públicos asíncronos
getProtectedMethods()list[str]Métodos protegidos
getProtectedSyncMethods()list[str]Métodos protegidos síncronos
getProtectedAsyncMethods()list[str]Métodos protegidos asíncronos
getPrivateMethods()list[str]Métodos privados
getPrivateSyncMethods()list[str]Métodos privados síncronos
getPrivateAsyncMethods()list[str]Métodos privados asíncronos
getPublicClassMethods()list[str]Métodos de clase públicos
getPublicClassSyncMethods()list[str]Métodos de clase públicos síncronos
getPublicClassAsyncMethods()list[str]Métodos de clase públicos asíncronos
getProtectedClassMethods()list[str]Métodos de clase protegidos
getProtectedClassSyncMethods()list[str]Métodos de clase protegidos síncronos
getProtectedClassAsyncMethods()list[str]Métodos de clase protegidos asíncronos
getPrivateClassMethods()list[str]Métodos de clase privados
getPrivateClassSyncMethods()list[str]Métodos de clase privados síncronos
getPrivateClassAsyncMethods()list[str]Métodos de clase privados asíncronos
getPublicStaticMethods()list[str]Métodos estáticos públicos
getPublicStaticSyncMethods()list[str]Métodos estáticos públicos síncronos
getPublicStaticAsyncMethods()list[str]Métodos estáticos públicos asíncronos
getProtectedStaticMethods()list[str]Métodos estáticos protegidos
getProtectedStaticSyncMethods()list[str]Métodos estáticos protegidos síncronos
getProtectedStaticAsyncMethods()list[str]Métodos estáticos protegidos asíncronos
getPrivateStaticMethods()list[str]Métodos estáticos privados
getPrivateStaticSyncMethods()list[str]Métodos estáticos privados síncronos
getPrivateStaticAsyncMethods()list[str]Métodos estáticos privados asíncronos
getDunderMethods()list[str]Métodos dunder
getMagicMethods()list[str]Alias de getDunderMethods
getProperties()list[str]Todas las propiedades
getPublicProperties()list[str]Propiedades públicas
getProtectedProperties()list[str]Propiedades protegidas
getPrivateProperties()list[str]Propiedades privadas
getPropertySignature(name)SignatureFirma del getter de propiedad
getPropertyDocstring(name)str | NoneDocstring del getter
constructorSignature()SignatureDependencias del constructor
methodSignature(name)SignatureDependencias de un método
clearCache()NoneLimpia toda la caché