ReflectionConcrete
ReflectionConcrete inspecciona una clase sin crear una instancia. Permite construir catálogos de acciones, verificar convenciones y consultar firmas para herramientas de desarrollo. También puede modificar datos y eliminar métodos de la clase original.
Los ejemplos siguientes forman un recorrido ejecutable: guarda el bloque inicial y los fragmentos posteriores, en orden, en un archivo .py. La recuperación de código fuente necesita ese archivo; una clase creada en la consola interactiva puede no tener fuente recuperable.
Construcción y caso de ejemplo
Sección titulada «Construcción y caso de ejemplo»__init__(self, concrete: type) -> Noneconcrete es obligatorio y debe satisfacer Reflection.isConcreteClass(). Rechaza instancias, callables que no sean clases, clases abstractas y las otras categorías que excluye ese predicado. No basta con decir «no abstracta»: una clase que hereda directamente de ABC también se rechaza. Algunas clases incorporadas, como int, pasan la comprobación; su código fuente puede no estar disponible.
from orionis.introspection import ReflectionConcrete
class Parent: inherited = "base"
def inheritedMethod(self) -> str: return "base"
class ReportService(Parent): """Report endpoint metadata."""
format: str = "json" _label: str = "reports" __token: str = "secret" __feature__ = "reports" declared_only: str
def __init__(self, limit: int = 10) -> None: self.instance_only = limit
def render(self, item_id: int, mode: str = "brief") -> str: return f"{item_id}:{mode}"
def summary(self) -> str: return "summary"
async def fetch(self) -> str: return "data"
def _check(self) -> bool: return True
async def _fetch(self) -> str: return "data"
def __sign(self) -> str: return "signature"
async def __fetch(self) -> str: return "data"
@staticmethod def normalize() -> str: return "json"
@staticmethod async def normalizeAsync() -> str: return "json"
@classmethod def build(cls) -> str: return cls.__name__
@classmethod async def buildAsync(cls) -> str: return cls.__name__
@staticmethod def _normalize() -> str: return "json"
@staticmethod async def _normalizeAsync() -> str: return "json"
@classmethod def _build(cls) -> str: return cls.__name__
@classmethod async def _buildAsync(cls) -> str: return cls.__name__
@staticmethod def __normalize() -> str: return "json"
@staticmethod async def __normalizeAsync() -> str: return "json"
@classmethod def __build(cls) -> str: return cls.__name__
@classmethod async def __buildAsync(cls) -> str: return cls.__name__
@property def title(self) -> str: """Report title.""" return self.format
@property def _title(self) -> str: """Report title.""" return self.format
@property def __title(self) -> str: """Report title.""" return self.format
def __repr__(self) -> str: return "Report"
r = ReflectionConcrete(ReportService)Importa desde orionis.introspection; también existe la ruta directa orionis.introspection.concretes.reflection. Los métodos de consulta son síncronos, aunque los miembros inspeccionados puedan ser async.
Alcance de la clasificación
Sección titulada «Alcance de la clasificación»El escaneo recorre solo Clase.__dict__, no la MRO. Los getters de colecciones excluyen miembros heredados; getBaseClasses() permite visitar las bases explícitamente. Un campo creado con self.campo no es un dato de clase, y una anotación sin valor no aparece entre los atributos.
La separación distingue datos, property, staticmethod, classmethod y otros callables. No comprueba que todo callable sea una función de instancia convencional. Para decidir async utiliza inspect.iscoroutinefunction(), no ejecuta el miembro: un generador asíncrono o una función síncrona que devuelve un awaitable no se convierten por eso en corrutinas.
Los nombres públicos no comienzan con _; los protegidos usan _; los privados se reconocen por el prefijo de mangling de la clase y se presentan como __nombre. Los dunder terminan también en __ y se consultan aparte. La normalización reproduce el prefijo que Python genera al quitar los _ iniciales del nombre de la clase.
Usa nombres privados tal como están escritos en el código ("__sign"), no "_ReportService__sign". La clasificación compara prefijos, no aplica un control de acceso ni impide usar un miembro privado.
Identidad, documentación y fuente
Sección titulada «Identidad, documentación y fuente»getClass
getClass(self) -> typeDevuelve el objeto de clase original (type), sin construirlo.
assert r.getClass() is ReportServicegetClassName
getClassName(self) -> strDevuelve el __name__ capturado al construir el wrapper como str, no __qualname__. clearCache() no vuelve a capturarlo.
assert r.getClassName() == "ReportService"getModuleName
getModuleName(self) -> strDevuelve el nombre del módulo declarado por la clase como str.
assert r.getModuleName() == ReportService.__module__getModuleWithClassName
getModuleWithClassName(self) -> strDevuelve modulo.NombreClase como str, con el nombre de clase capturado al construir el wrapper y el módulo leído al calcular este resultado. Lo almacena en caché. No agrega los ámbitos de una clase anidada.
assert r.getModuleWithClassName() == f"{ReportService.__module__}.ReportService"getDocstring
getDocstring(self) -> str | NoneDevuelve __doc__ o None; no aplica limpieza ni hereda la documentación de otra clase.
assert r.getDocstring() == "Report endpoint metadata."getBaseClasses
getBaseClasses(self) -> list[type]Devuelve una lista de bases directas (type); no recorre la MRO completa.
assert Parent in r.getBaseClasses()getSourceCode
getSourceCode(self, method: str | None = None) -> str | NoneSin method (predeterminado None), devuelve el código de la clase. Con un nombre de método propio, devuelve su fuente; admite privados. Devuelve None si falta el método, si es dunder (queda fuera de hasMethod()) o si inspect.getsource() lanza TypeError/OSError. No ejecuta el método.
assert "class ReportService" in r.getSourceCode()assert "def render" in r.getSourceCode("render")assert "def __sign" in r.getSourceCode("__sign")assert r.getSourceCode("missing") is Noneassert r.getSourceCode("__repr__") is NonegetFile
getFile(self) -> strDevuelve la ruta del archivo de la clase como str. Convierte el TypeError de inspect.getfile() en ValueError; no garantiza que el archivo siga existiendo.
assert r.getFile().endswith(".py")getAnnotations
getAnnotations(self) -> dictDevuelve un dict de anotaciones de la clase, incluso campos anotados sin valor. Quita el prefijo de clase de los nombres privados y no analiza las anotaciones de métodos.
assert "declared_only" in r.getAnnotations()assert "__token" in r.getAnnotations()Datos de clase
Sección titulada «Datos de clase»hasAttribute
hasAttribute(self, attribute: str) -> boolattribute es el nombre obligatorio de un dato declarado en la clase. Devuelve bool; no incluye métodos, propiedades, miembros heredados ni valores creados únicamente por el constructor.
assert r.hasAttribute("format")assert not r.hasAttribute("declared_only")assert not r.hasAttribute("inherited")assert not r.hasAttribute("instance_only")getAttribute
getAttribute(self, name: str, default: Any = None) -> Anyname es obligatorio; default vale None. Primero busca en datos propios normalizados y utiliza getattr(Clase, name, default) como respaldo: puede devolver miembros heredados, métodos o descriptores aunque hasAttribute() sea False. Ese respaldo se evalúa incluso si hay un dato en caché, por lo que un descriptor personalizado puede tener efectos o lanzar excepciones.
assert r.getAttribute("format") == "json"assert r.getAttribute("missing", "fallback") == "fallback"assert r.getAttribute("inherited") == "base"assert not r.hasAttribute("inherited")getAttributes
getAttributes(self) -> dictDevuelve un dict con datos públicos, protegidos, privados normalizados y dunder no excluidos, en ese orden de combinación. No contiene campos de instancias ni anotaciones sin valor.
attributes = r.getAttributes()assert attributes["format"] == "json"assert attributes["__token"] == "secret"getPublicAttributes
getPublicAttributes(self) -> dictDevuelve un dict de datos cuyos nombres no comienzan con _.
assert r.getPublicAttributes()["format"] == "json"getProtectedAttributes
getProtectedAttributes(self) -> dictDevuelve un dict de datos con _ inicial que no son privados ni dunder.
assert r.getProtectedAttributes()["_label"] == "reports"getPrivateAttributes
getPrivateAttributes(self) -> dictDevuelve un dict de datos privados. Sus claves conservan __ pero omiten el prefijo de clase que introduce Python.
assert r.getPrivateAttributes()["__token"] == "secret"getDunderAttributes
getDunderAttributes(self) -> dictDevuelve un dict de datos __nombre__ personalizados. La implementación excluye metadatos de Python como __dict__, __module__, __doc__ y __annotations__.
assert r.getDunderAttributes()["__feature__"] == "reports"assert "__module__" not in r.getDunderAttributes()getMagicAttributes
getMagicAttributes(self) -> dictAlias de getDunderAttributes(); devuelve el mismo diccionario almacenado.
assert r.getMagicAttributes() is r.getDunderAttributes()setAttribute
setAttribute(self, name: str, value: object) -> boolname debe ser un identificador Python válido que no sea palabra reservada (ValueError en caso contrario). value es obligatorio y no puede ser callable (TypeError). Modifica la clase original y devuelve True; admite __privados. No valida anotaciones ni actualiza __abstractmethods__.
assert r.setAttribute("extra_label", "export") is Trueassert ReportService.extra_label == "export"assert r.removeAttribute("extra_label") is TrueremoveAttribute
removeAttribute(self, name: str) -> boolname identifica un dato propio, usando su nombre original si es privado. Elimina el atributo real y devuelve True. Si no está en la clasificación de datos, lanza ValueError; las restricciones del metatipo pueden propagarse.
r.setAttribute("__temporary", 20)assert r.removeAttribute("__temporary") is Trueassert not r.hasAttribute("__temporary")Métodos de instancia
Sección titulada «Métodos de instancia»getMethods
getMethods(self) -> list[str]Devuelve list[str]: métodos de instancia, de clase y estáticos, cada categoría ordenada por visibilidad pública, protegida y privada. Excluye propiedades y dunder; no ordena alfabéticamente.
methods = r.getMethods()assert "render" in methods and "build" in methods and "normalize" in methodsassert "title" not in methods and "__repr__" not in methodsgetPublicMethods
getPublicMethods(self) -> list[str]Devuelve list[str] de métodos de instancia públicos, incluyendo síncronos y asíncronos. No ejecuta los métodos. No recibe argumentos.
assert "summary" in r.getPublicMethods()getPublicSyncMethods
getPublicSyncMethods(self) -> list[str]Devuelve list[str] de métodos de instancia públicos que no son funciones de corrutina. No ejecuta los métodos. No recibe argumentos.
assert "summary" in r.getPublicSyncMethods()assert "fetch" not in r.getPublicSyncMethods()getPublicAsyncMethods
getPublicAsyncMethods(self) -> list[str]Devuelve list[str] de métodos de instancia públicos que cumplen inspect.iscoroutinefunction(). No ejecuta los métodos. No recibe argumentos.
assert "fetch" in r.getPublicAsyncMethods()assert "summary" not in r.getPublicAsyncMethods()getProtectedMethods
getProtectedMethods(self) -> list[str]Devuelve list[str] de métodos de instancia protegidos, incluyendo síncronos y asíncronos. No ejecuta los métodos. No recibe argumentos.
assert "_check" in r.getProtectedMethods()getProtectedSyncMethods
getProtectedSyncMethods(self) -> list[str]Devuelve list[str] de métodos de instancia protegidos que no son funciones de corrutina. No ejecuta los métodos. No recibe argumentos.
assert "_check" in r.getProtectedSyncMethods()assert "_fetch" not in r.getProtectedSyncMethods()getProtectedAsyncMethods
getProtectedAsyncMethods(self) -> list[str]Devuelve list[str] de métodos de instancia protegidos que cumplen inspect.iscoroutinefunction(). No ejecuta los métodos. No recibe argumentos.
assert "_fetch" in r.getProtectedAsyncMethods()assert "_check" not in r.getProtectedAsyncMethods()getPrivateMethods
getPrivateMethods(self) -> list[str]Devuelve list[str] de métodos de instancia privados, incluyendo síncronos y asíncronos. Los resultados usan __nombre, sin el prefijo de clase. No ejecuta los métodos. No recibe argumentos.
assert "__sign" in r.getPrivateMethods()getPrivateSyncMethods
getPrivateSyncMethods(self) -> list[str]Devuelve list[str] de métodos de instancia privados que no son funciones de corrutina. Los resultados usan __nombre, sin el prefijo de clase. No ejecuta los métodos. No recibe argumentos.
assert "__sign" in r.getPrivateSyncMethods()assert "__fetch" not in r.getPrivateSyncMethods()getPrivateAsyncMethods
getPrivateAsyncMethods(self) -> list[str]Devuelve list[str] de métodos de instancia privados que cumplen inspect.iscoroutinefunction(). Los resultados usan __nombre, sin el prefijo de clase. No ejecuta los métodos. No recibe argumentos.
assert "__fetch" in r.getPrivateAsyncMethods()assert "__sign" not in r.getPrivateAsyncMethods()Métodos de clase
Sección titulada «Métodos de clase»getPublicClassMethods
getPublicClassMethods(self) -> list[str]Devuelve list[str] de métodos de clase (@classmethod) públicos, incluyendo síncronos y asíncronos. No ejecuta los métodos. No recibe argumentos.
assert "build" in r.getPublicClassMethods()getPublicClassSyncMethods
getPublicClassSyncMethods(self) -> list[str]Devuelve list[str] de métodos de clase (@classmethod) públicos que no son funciones de corrutina. No ejecuta los métodos. No recibe argumentos.
assert "build" in r.getPublicClassSyncMethods()assert "buildAsync" not in r.getPublicClassSyncMethods()getPublicClassAsyncMethods
getPublicClassAsyncMethods(self) -> list[str]Devuelve list[str] de métodos de clase (@classmethod) públicos que cumplen inspect.iscoroutinefunction(). No ejecuta los métodos. No recibe argumentos.
assert "buildAsync" in r.getPublicClassAsyncMethods()assert "build" not in r.getPublicClassAsyncMethods()getProtectedClassMethods
getProtectedClassMethods(self) -> list[str]Devuelve list[str] de métodos de clase (@classmethod) protegidos, incluyendo síncronos y asíncronos. No ejecuta los métodos. No recibe argumentos.
assert "_build" in r.getProtectedClassMethods()getProtectedClassSyncMethods
getProtectedClassSyncMethods(self) -> list[str]Devuelve list[str] de métodos de clase (@classmethod) protegidos que no son funciones de corrutina. No ejecuta los métodos. No recibe argumentos.
assert "_build" in r.getProtectedClassSyncMethods()assert "_buildAsync" not in r.getProtectedClassSyncMethods()getProtectedClassAsyncMethods
getProtectedClassAsyncMethods(self) -> list[str]Devuelve list[str] de métodos de clase (@classmethod) protegidos que cumplen inspect.iscoroutinefunction(). No ejecuta los métodos. No recibe argumentos.
assert "_buildAsync" in r.getProtectedClassAsyncMethods()assert "_build" not in r.getProtectedClassAsyncMethods()getPrivateClassMethods
getPrivateClassMethods(self) -> list[str]Devuelve list[str] de métodos de clase (@classmethod) privados, incluyendo síncronos y asíncronos. Los resultados usan __nombre, sin el prefijo de clase. No ejecuta los métodos. No recibe argumentos.
assert "__build" in r.getPrivateClassMethods()getPrivateClassSyncMethods
getPrivateClassSyncMethods(self) -> list[str]Devuelve list[str] de métodos de clase (@classmethod) privados que no son funciones de corrutina. Los resultados usan __nombre, sin el prefijo de clase. No ejecuta los métodos. No recibe argumentos.
assert "__build" in r.getPrivateClassSyncMethods()assert "__buildAsync" not in r.getPrivateClassSyncMethods()getPrivateClassAsyncMethods
getPrivateClassAsyncMethods(self) -> list[str]Devuelve list[str] de métodos de clase (@classmethod) privados que cumplen inspect.iscoroutinefunction(). Los resultados usan __nombre, sin el prefijo de clase. No ejecuta los métodos. No recibe argumentos.
assert "__buildAsync" in r.getPrivateClassAsyncMethods()assert "__build" not in r.getPrivateClassAsyncMethods()Métodos estáticos
Sección titulada «Métodos estáticos»getPublicStaticMethods
getPublicStaticMethods(self) -> list[str]Devuelve list[str] de métodos estáticos (@staticmethod) públicos, incluyendo síncronos y asíncronos. No ejecuta los métodos. No recibe argumentos.
assert "normalize" in r.getPublicStaticMethods()getPublicStaticSyncMethods
getPublicStaticSyncMethods(self) -> list[str]Devuelve list[str] de métodos estáticos (@staticmethod) públicos que no son funciones de corrutina. No ejecuta los métodos. No recibe argumentos.
assert "normalize" in r.getPublicStaticSyncMethods()assert "normalizeAsync" not in r.getPublicStaticSyncMethods()getPublicStaticAsyncMethods
getPublicStaticAsyncMethods(self) -> list[str]Devuelve list[str] de métodos estáticos (@staticmethod) públicos que cumplen inspect.iscoroutinefunction(). No ejecuta los métodos. No recibe argumentos.
assert "normalizeAsync" in r.getPublicStaticAsyncMethods()assert "normalize" not in r.getPublicStaticAsyncMethods()getProtectedStaticMethods
getProtectedStaticMethods(self) -> list[str]Devuelve list[str] de métodos estáticos (@staticmethod) protegidos, incluyendo síncronos y asíncronos. No ejecuta los métodos. No recibe argumentos.
assert "_normalize" in r.getProtectedStaticMethods()getProtectedStaticSyncMethods
getProtectedStaticSyncMethods(self) -> list[str]Devuelve list[str] de métodos estáticos (@staticmethod) protegidos que no son funciones de corrutina. No ejecuta los métodos. No recibe argumentos.
assert "_normalize" in r.getProtectedStaticSyncMethods()assert "_normalizeAsync" not in r.getProtectedStaticSyncMethods()getProtectedStaticAsyncMethods
getProtectedStaticAsyncMethods(self) -> list[str]Devuelve list[str] de métodos estáticos (@staticmethod) protegidos que cumplen inspect.iscoroutinefunction(). No ejecuta los métodos. No recibe argumentos.
assert "_normalizeAsync" in r.getProtectedStaticAsyncMethods()assert "_normalize" not in r.getProtectedStaticAsyncMethods()getPrivateStaticMethods
getPrivateStaticMethods(self) -> list[str]Devuelve list[str] de métodos estáticos (@staticmethod) privados, incluyendo síncronos y asíncronos. Los resultados usan __nombre, sin el prefijo de clase. No ejecuta los métodos. No recibe argumentos.
assert "__normalize" in r.getPrivateStaticMethods()getPrivateStaticSyncMethods
getPrivateStaticSyncMethods(self) -> list[str]Devuelve list[str] de métodos estáticos (@staticmethod) privados que no son funciones de corrutina. Los resultados usan __nombre, sin el prefijo de clase. No ejecuta los métodos. No recibe argumentos.
assert "__normalize" in r.getPrivateStaticSyncMethods()assert "__normalizeAsync" not in r.getPrivateStaticSyncMethods()getPrivateStaticAsyncMethods
getPrivateStaticAsyncMethods(self) -> list[str]Devuelve list[str] de métodos estáticos (@staticmethod) privados que cumplen inspect.iscoroutinefunction(). Los resultados usan __nombre, sin el prefijo de clase. No ejecuta los métodos. No recibe argumentos.
assert "__normalizeAsync" in r.getPrivateStaticAsyncMethods()assert "__normalize" not in r.getPrivateStaticAsyncMethods()Existencia, cambios y métodos dunder
Sección titulada «Existencia, cambios y métodos dunder»hasMethod
hasMethod(self, name: str) -> boolname es obligatorio; devuelve bool para métodos propios de instancia, clase o estáticos. Usa nombres privados sin mangling. Los dunder se consultan por separado y aquí devuelven False.
assert r.hasMethod("render")assert r.hasMethod("__sign")assert not r.hasMethod("__repr__")assert not r.hasMethod("inheritedMethod")setMethod
setMethod(self, name: str, method: Callable) -> boolname y method son obligatorios. Añade un callable a la clase y devuelve True; admite __privados. Rechaza nombres ya clasificados o identificadores inválidos con ValueError, y valores no callable con TypeError. Para reemplazar un método reconocido, elimínalo primero. El chequeo de duplicados no incluye heredados, datos, propiedades ni dunder: no lo uses para garantizar que cualquier miembro sea nuevo. El callable se guarda tal como se recibe; una función normal pasa a ser método de instancia, sin crear automáticamente decoradores.
def export(self, prefix: str = "report") -> str: return f"{prefix}:{self.format}"
assert r.setMethod("export", export) is Trueassert ReportService().export() == "report:json"assert r.removeMethod("export") is TrueUn descriptor staticmethod es callable y puede conservarse al registrarlo. Un descriptor classmethod no es callable y setMethod() lo rechaza con TypeError; no es una API general para instalar cualquier descriptor.
def download() -> str: return "report.csv"
assert r.setMethod("download", staticmethod(download)) is Trueassert "download" in r.getPublicStaticMethods()assert ReportService.download() == "report.csv"r.removeMethod("download")
try: r.setMethod("buildAgain", classmethod(lambda cls: cls.__name__))except TypeError: passelse: raise AssertionError("A classmethod descriptor is not callable")removeMethod
removeMethod(self, name: str) -> boolElimina de la clase el método propio name y devuelve True; si no aparece en hasMethod(), lanza ValueError. Admite privados y descriptores estáticos/de clase. No sirve para borrar dunder ni métodos heredados.
original_summary = ReportService.__dict__["summary"]assert r.removeMethod("summary") is Trueassert not r.hasMethod("summary")setattr(ReportService, "summary", original_summary)r.clearCache()getDunderMethods
getDunderMethods(self) -> list[str]Devuelve list[str] de callables propios __nombre__ que no son properties, staticmethods ni classmethods. Incluye __init__ si se declaró en la clase.
assert "__repr__" in r.getDunderMethods()assert "__init__" in r.getDunderMethods()getMagicMethods
getMagicMethods(self) -> list[str]Alias de getDunderMethods(); devuelve la misma lista almacenada.
assert r.getMagicMethods() is r.getDunderMethods()Propiedades sin construir la clase
Sección titulada «Propiedades sin construir la clase»getProperties
getProperties(self) -> list[str]Devuelve list[str] de descriptores property propios. Conserva el orden de declaración, normaliza los privados y no ejecuta los getters.
assert r.getProperties() == ["title", "_title", "__title"]getPublicProperties
getPublicProperties(self) -> list[str]Devuelve list[str] de propiedades públicas.
assert r.getPublicProperties() == ["title"]getProtectedProperties
getProtectedProperties(self) -> list[str]Devuelve list[str] de propiedades protegidas.
assert r.getProtectedProperties() == ["_title"]getPrivateProperties
getPrivateProperties(self) -> list[str]Devuelve list[str] de propiedades privadas usando su nombre original.
assert r.getPrivateProperties() == ["__title"]getProperty
getProperty(self, name: str) -> Anyname es obligatorio. Ejecuta fget(Clase) y devuelve el resultado (Any): el getter recibe la clase, no una instancia. Funciona si solo necesita datos de clase, como title en el ejemplo. Una propiedad que usa campos creados por __init__ puede lanzar AttributeError; los errores y efectos del getter se propagan. No es una forma de construir ni de consultar una instancia. Admite privados y propiedades heredadas; lanza ValueError si falta y TypeError si no es property.
assert r.getProperty("title") == "json"assert r.getProperty("__title") == "json"Una propiedad de instancia no debe evaluarse de esta manera:
class StatefulReport: def __init__(self, label: str) -> None: self.label = label
@property def title(self) -> str: return self.label
stateful = ReflectionConcrete(StatefulReport)try: stateful.getProperty("title")except AttributeError: passelse: raise AssertionError("The class has no instance label")
assert StatefulReport("Daily report").title == "Daily report"getPropertySignature
getPropertySignature(self, name: str) -> inspect.Signaturename es obligatorio. Devuelve inspect.Signature del getter fget, incluido self, sin ejecutarlo. Admite privados e incluso propiedades heredadas accesibles por getattr(). Lanza ValueError si falta y TypeError si no es property o no puede inspeccionarse su getter.
assert list(r.getPropertySignature("title").parameters) == ["self"]assert list(r.getPropertySignature("__title").parameters) == ["self"]getPropertyDocstring
getPropertyDocstring(self, name: str) -> str | Nonename es obligatorio. Devuelve str | None con el docstring de fget; sin getter devuelve None. Admite privados y propiedades heredadas. Lanza ValueError si falta y TypeError si el atributo no es property.
assert r.getPropertyDocstring("title") == "Report title."assert r.getPropertyDocstring("__title") == "Report title."Firmas e información para dependencias
Sección titulada «Firmas e información para dependencias»getMethodSignature
getMethodSignature(self, name: str) -> inspect.Signaturename es obligatorio. Devuelve inspect.Signature sin invocar el método: conserva self en métodos de instancia y omite cls al obtener un classmethod ligado. Lanza ValueError si el nombre no está clasificado, TypeError si dejó de ser callable; también pueden propagarse errores de inspección.
signature = r.getMethodSignature("render")assert list(signature.parameters) == ["self", "item_id", "mode"]assert "cls" not in r.getMethodSignature("build").parametersassert "self" not in r.getMethodSignature("normalize").parametersgetConstructorSignature
getConstructorSignature(self) -> inspect.SignatureNo recibe argumentos. Devuelve el inspect.Signature de Clase.__init__, con self. No crea el objeto ni clasifica sus dependencias. Los errores de inspect.signature() se propagan.
signature = r.getConstructorSignature()assert list(signature.parameters) == ["self", "limit"]assert signature.parameters["limit"].default == 10constructorSignature
constructorSignature(self) -> SignatureDevuelve el Signature de Orionis para las dependencias de __init__, sin construir la clase. Sus mapas resolved, unresolved y ordered contienen Argument. No es inspect.Signature ni resuelve instancias de servicios.
analysis = r.constructorSignature()assert list(analysis.ordered) == ["limit"]assert analysis.resolved["limit"].default == 10methodSignature
methodSignature(self, method_name: str) -> Signaturemethod_name es obligatorio. Devuelve el Signature de dependencias de un método propio; quita self/cls y clasifica sus argumentos sin ejecutarlo. Lanza AttributeError si hasMethod() es falso; los errores del analizador se propagan. Admite privados.
analysis = r.methodSignature("render")assert list(analysis.ordered) == ["item_id", "mode"]assert "item_id" in analysis.unresolvedassert analysis.resolved["mode"].default == "brief"Estos dos últimos métodos delegan en ReflectDependencies. resolved significa que existe información suficiente de tipo o valor predeterminado; no implica que se haya creado o registrado un servicio. El argumento requerido builtin item_id: int permanece sin resolver, mientras que mode="brief" tiene un valor predeterminado conocido.
Caché local y operadores de acceso
Sección titulada «Caché local y operadores de acceso»El primer getter de miembros realiza el escaneo; las listas y diccionarios devueltos son los objetos almacenados, no copias defensivas. No los modifiques para «editar» la clase: eso altera la vista en caché y puede producir resultados incoherentes. Usa los métodos de modificación o crea una copia de la respuesta.
setAttribute(), removeAttribute(), setMethod() y removeMethod() limpian toda la caché de este wrapper. Los cambios hechos directamente sobre la clase o mediante otro wrapper requieren clearCache() en cada reflector afectado.
El nombre de clase y el prefijo privado se capturan en el constructor; clearCache() no los actualiza. getModuleName() y getDocstring() leen directamente la clase. getModuleWithClassName() conserva su resultado hasta limpiar la caché. Si modificas __name__, crea otro wrapper.
Los operadores siguientes acceden a la caché del wrapper, no a los atributos de la clase. Usa claves propias que no coincidan con las internas (attributes, methods, etc.); sobrescribir o borrar claves internas puede romper la consistencia del escaneo.
__setitem__
__setitem__(self, key: str, value: object) -> NoneGuarda value bajo la clave obligatoria key; devuelve None. No modifica la clase.
r["app:note"] = "reviewed"assert r["app:note"] == "reviewed"__getitem__
__getitem__(self, key: str) -> object | NoneDevuelve el valor bajo key o None si no existe; no lanza KeyError. Una clave guardada con None se distingue usando in.
assert r["app:note"] == "reviewed"assert r["app:absent"] is None__contains__
__contains__(self, key: str) -> boolDevuelve bool indicando si key está almacenada, incluso cuando su valor es None.
r["app:empty"] = Noneassert "app:empty" in rassert "app:absent" not in r__delitem__
__delitem__(self, key: str) -> NoneElimina key, devuelve None e ignora claves inexistentes.
del r["app:note"]del r["app:absent"]assert "app:note" not in rclearCache
clearCache(self) -> NoneDevuelve None. Descarta todos los datos almacenados en este wrapper, incluidas las claves añadidas con corchetes. La siguiente consulta vuelve a inspeccionar; no deshace cambios de la clase ni vacía la caché global de dependencias.
r["app:note"] = "cached"assert r.clearCache() is Noneassert "app:note" not in rassert "render" in r.getPublicMethods()Integración con inyección de dependencias
Sección titulada «Integración con inyección de dependencias»El wrapper necesita saber qué clase inspeccionar. No supongas que anotar un parámetro como ReflectionConcrete selecciona automáticamente el contrato o componente de tu aplicación. Construye el reflector cuando conoces la clase, o encapsúlalo en un servicio propio que el contenedor pueda resolver. No existe un binding nativo que elija esa clase por ti.
from orionis.http import JSONResponse
class ReportCatalog: def __init__(self) -> None: self.reflection = ReflectionConcrete(ReportService)
def actions(self) -> list[str]: return list(self.reflection.getPublicMethods())
class ReportExporter: def __init__(self, catalog: ReportCatalog) -> None: self.catalog = catalog
def actions(self) -> list[str]: return self.catalog.actions()
class MetadataController: async def __call__(self, catalog: ReportCatalog) -> JSONResponse: return JSONResponse({"actions": catalog.actions()})Aquí se inyecta ReportCatalog, un servicio de la aplicación con constructor sin argumentos. El catálogo crea explícitamente el reflector y devuelve una copia de la lista. La inyección en el constructor de otro servicio funciona con la misma anotación catalog: ReportCatalog. El acceso directo sigue siendo válido fuera de controladores. Consulta el contenedor para los registros, ciclos de vida y contratos personalizados.
Errores y límites que conviene conocer
Sección titulada «Errores y límites que conviene conocer»Las consultas no ejecutan acciones ni aplican anotaciones como validación de datos. Los cambios son reales y afectan a todos los usuarios de la clase dentro del proceso; no crean una copia y no se revierten al borrar el reflector. Una operación puede fallar por restricciones de descriptores o metaclases, y esas excepciones se propagan.
Para consultar propiedades que dependen de una instancia, crea o recibe esa instancia y usa ReflectionInstance. getProperty() de este wrapper solo pasa la clase al getter.
Un nombre que getDunderMethods() devuelve no es válido automáticamente para hasMethod(), removeMethod(), getMethodSignature() ni methodSignature(): esas operaciones usan la lista de métodos no dunder. Las propiedades se consultan mediante sus APIs específicas.
Si cambias funciones dinámicamente, limpiar este wrapper no vacía las cachés compartidas de ReflectDependencies. Las funciones nuevas se analizan por su identidad, pero modificar anotaciones o valores predeterminados de la misma función puede conservar un análisis anterior; revisa la guía de dependencias.