Dependencias, descubrimiento y referencia
Esta es una API avanzada para extender una aplicación. Para la inyección habitual de servicios, empieza por el contenedor. Usa los ejemplos de abajo al construir una herramienta propia de descubrimiento o inspección; no requieren un checkout del código fuente del framework.
API pública
Sección titulada «API pública»Reflection
Sección titulada «Reflection»instance(value),abstract(cls),concrete(cls),module(name)ycallable(fn)construyen wrappers.isAbstract,isConcreteClass,isInstance,isGeneric,isProtocoleisTypingConstructaplican clasificaciones de Orionis.isAsyncGen,isAsyncGenFunction,isAwaitable,isBuiltIn,isClass,isCode,isCoroutine,isCoroutineFunction,isDataDescriptor,isFrame,isFunction,isGenerator,isGeneratorFunction,isGetSetDescriptor,isMemberDescriptor,isMethod,isMethodDescriptor,isModule,isRoutineeisTracebackexponen predicados de runtime.
ReflectionCallable
Sección titulada «ReflectionCallable»Proporciona getCallable, getName, getModuleName, getModuleWithCallableName, getDocstring, getSourceCode, getFile, getSignature, getDependencies y clearCache. Su protocolo de items es una pequeña caché en memoria accesible al usuario.
Wrappers de clase e instancia
Sección titulada «Wrappers de clase e instancia»Ambas familias exponen identidad, módulo, docstring, bases, fuente, archivo, anotaciones, atributos, métodos, propiedades, firmas inspect, firmas de dependencias y limpieza de caché. Los numerosos métodos getPublic*, getProtected* y getPrivate* seleccionan visibilidad; Sync y Async refinan el tipo de método. Los wrappers concretos y de instancia también permiten mutación controlada de atributos/métodos.
ReflectionAbstract ofrece la misma superficie orientada a lectura para clases abstractas y conserva la semántica de miembros abstractos.
ReflectionModule
Sección titulada «ReflectionModule»Importa un módulo dotted y expone clases, constantes, funciones, imports, fuente y archivo. Los getters dividen clases y constantes por visibilidad; los de funciones separan además sync de async. Su protocolo mapping lee o muta atributos del módulo.
ReflectDependencies y Signature
Sección titulada «ReflectDependencies y Signature»constructorSignature(), methodSignature(name) y callableSignature() devuelven un Signature. La entidad ofrece predicados y selectores: hasParameters, noArgumentsRequired, hasUnresolvedArguments, getResolved, getUnresolved, getAllOrdered, getPositionalOnly, getKeywordOnly, conversiones y arguments().
ModuleInspector
Sección titulada «ModuleInspector»discoverModules(base_path, target_path)devuelve módulos dotted bajo una base segura.loadClass(module_path, class_name)oloadClass(metadata=...)importa una clase.fileImportsAny(path, targets, allow_empty=False)analiza imports sin ejecutar el archivo.discoverFrozenDataclasses(modules)importa módulos y devuelve dataclasses frozen declaradas allí.
Flujos de trabajo comunes
Sección titulada «Flujos de trabajo comunes»Construir argumentos del contenedor
Sección titulada «Construir argumentos del contenedor»Refleje el constructor o handler seleccionado. Resuelva valores de Signature.resolved desde el contenedor o decodificador de schema y exija al llamador los builtins sin resolver o parámetros sin anotación. Conserve ordered e is_keyword_only al invocar el objetivo.
Descubrir componentes de aplicación
Sección titulada «Descubrir componentes de aplicación»Use discoverModules() bajo una raíz conocida, filtre opcionalmente archivos con fileImportsAny() y cargue una clase declarada con loadClass(). Orionis aplica este patrón a comandos, migraciones, seeders, entidades de configuración y jobs en cola.
Inspeccionar código sin mutarlo
Sección titulada «Inspeccionar código sin mutarlo»Elija el wrapper más específico y use sus getters clasificados. Recuperar fuente/archivo puede fallar para objetos dinámicos o builtin; aun así pueden estar disponibles metadatos y firmas inspect. Trate diccionarios/listas mutables devueltos como resultados de reflexión, no como registros vivos autoritativos.
Modificar miembros reflejados
Sección titulada «Modificar miembros reflejados»setAttribute, removeAttribute, setMethod, la asignación de items de módulo y su borrado afectan la clase, instancia o módulo real. Limpie la caché tras mutación externa; los métodos de mutación del wrapper invalidan los datos afectados. Restrinja esta capacidad a bootstrap, pruebas y metaprogramación controlada.
Configuración
Sección titulada «Configuración»Este módulo no tiene archivo de configuración de aplicación, variables de entorno, service provider, facade ni ajustes de I/O externo. Sus constantes operativas relevantes son límites de implementación: las firmas usan cachés LRU de 1.024 entradas, el descubrimiento excluye __pycache__ y site-packages, y se omiten nombres reconocidos de entornos virtuales cuando contienen pyvenv.cfg.
Integración con Orionis
Sección titulada «Integración con Orionis»El contenedor usa firmas de dependencias para resolver constructores e invocaciones sin inspeccionarlos repetidamente. Foundation descubre dataclasses frozen de configuración. Console descubre módulos de comandos; database descubre migraciones y seeders; queues carga clases de jobs; realtime lee metadatos de handlers. Estos consumidores importan utilidades concretas directamente en vez de resolver un servicio del contenedor.
Como la inspección está por debajo del contenedor, el paquete no depende de una instancia de aplicación. Puede usarse en bootstrap y herramientas antes de iniciar Orionis.
Errores y casos límite
Sección titulada «Errores y casos límite»- Cada wrapper rechaza una categoría incorrecta; por ejemplo, reflexión concreta rechaza clases abstractas, builtin, genéricas, protocolos y construcciones de typing.
ReflectionInstancerechaza objetos de clase, instancias builtin/ABC e instancias cuya clase se define en__main__.ReflectionCallableacepta funciones Python, métodos ligados, lambdas y callables con__code__; otros callables pueden rechazarse.- Buscar fuente y archivo puede producir
AttributeError,TypeErroro errores de inspección para objetos generados, interactivos o builtin. - Métodos/propiedades desconocidos producen
AttributeError; nombres de mutación inválidos y métodos no callable fallan en validación. - Anotaciones builtin requeridas como
intquedan sin resolver intencionalmente; un valor predeterminado resuelve el parámetro desde su tipo concreto. - Las referencias futuras se resuelven cuando es posible. Los nombres no disponibles permanecen como metadatos conservadores sin importarlos especulativamente.
discoverModulesfalla si el objetivo queda fuera de la base. El análisis AST devuelveFalsepara archivos ausentes, inválidos o no decodificables.discoverModules()yfileImportsAny()no ejecutan los archivos inspeccionados.loadClass(), la reflexión de módulos y el descubrimiento de dataclasses frozen importan código; limita esas operaciones a paquetes confiables.
Rendimiento y concurrencia
Sección titulada «Rendimiento y concurrencia»Los scans de clase/miembros recorren una vez y se guardan por wrapper. Las firmas inspect y de dependencias se memoizan, y la carga de módulos/clases combina la caché de importación de Python con una caché de clases de Orionis. Reutilice wrappers en hot paths y llame clearCache() solo tras mutación intencional.
Las cachés son locales al proceso. Las lecturas sirven para concurrencia normal bajo las garantías del runtime, pero mutar objetos reflejados y limpiar cachés no es transaccional. No modifique una clase/módulo compartido mientras otros threads o tasks lo inspeccionan o invocan. El recorrido del filesystem es síncrono y corresponde a bootstrap/herramientas, no al hot path de solicitudes.
Compatibilidad
Sección titulada «Compatibilidad»Orionis declara Python 3.14+. La reflexión depende del comportamiento de inspección de CPython/Python, incluidos descriptores, inspect.signature, resolución de anotaciones, name mangling y metadatos de importación. Objetos de extensiones, funciones generadas dinámicamente, aplicaciones congeladas y runtimes alternativos pueden no exponer fuente o archivo aunque otros métodos funcionen.
Estructura del módulo
Sección titulada «Estructura del módulo»| Ruta | Responsabilidad |
|---|---|
reflection.py | Factory y predicados generales de clasificación. |
callables/ | Metadatos, código, firma inspect y dependencias de funciones/métodos. |
abstract/ | Reflexión y clasificación de miembros de clases abstractas. |
concretes/ | Reflexión, mutación y firmas de clases concretas. |
instances/ | Estado de instancia y reflexión de miembros/propiedades de clase. |
modules/reflection.py | Clases, constantes, funciones, código y caché de módulos importados. |
modules/inspector.py | Descubrimiento, análisis AST, carga de clases y dataclasses frozen. |
dependencies/ | Resolución de firmas y entidades Argument / Signature. |
*/contracts/ | Contratos abstractos para cada especialización. |
Ejemplos
Sección titulada «Ejemplos»Analizar argumentos de inyección
Sección titulada «Analizar argumentos de inyección»from orionis.introspection import ReflectDependencies
class Repository: pass
def handler(repository: Repository, raw, *, limit=25): return repository, raw, limit
signature = ReflectDependencies(handler).callableSignature()assert list(signature.getAllOrdered()) == ["repository", "raw", "limit"]assert list(signature.getResolved()) == ["repository", "limit"]assert list(signature.getUnresolved()) == ["raw"]assert signature.getKeywordOnly()["limit"].default == 25print(signature.hasUnresolvedArguments())Descubrir módulos de aplicación sin importarlos
Sección titulada «Descubrir módulos de aplicación sin importarlos»Este programa independiente crea un directorio temporal con estructura de aplicación y lo elimina al salir. No necesita una base de datos, iniciar la aplicación ni acceder al directorio fuente del framework:
from pathlib import Pathfrom tempfile import TemporaryDirectoryfrom orionis.introspection import ModuleInspector
with TemporaryDirectory() as directory: root = Path(directory) jobs = root / "app" / "jobs" jobs.mkdir(parents=True) (jobs / "__init__.py").write_text("", encoding="utf-8") source = jobs / "report.py" source.write_text("from orionis.queues import BaseJob\n", encoding="utf-8")
modules = ModuleInspector.discoverModules(root, jobs) print(sorted(modules)) # ['app.jobs', 'app.jobs.report'] print(ModuleInspector.fileImportsAny(source, {"orionis.queues"})) # TruediscoverModules devuelve nombres de módulos separados por puntos; fileImportsAny analiza un AST sin ejecutar report.py. Encontrar un archivo no registra un job ni carga una clase. Para cargar una clase conocida desde un módulo importable y confiable, usa ModuleInspector.loadClass("pathlib", "Path"); devuelve pathlib.Path. En una aplicación, su raíz debe estar en la ruta de importación de Python antes de cargar módulos app.….