Skip to content

ReflectionAbstract

ReflectionAbstract inspects a class without creating an instance. Use it to build action catalogs, verify conventions and inspect signatures for development tools. It can also mutate data and remove methods on the original class.

The following examples form an executable walkthrough: save the initial block and subsequent snippets, in order, to a .py file. Source retrieval requires this file; a class created in an interactive console may not have retrievable source.

__init__(self, abstract: type) -> None

Required abstract must satisfy inspect.isabstract(): inheriting from ABC with no remaining abstract methods is insufficient. A non-abstract class raises TypeError; an invalid input lacking __name__ can also raise AttributeError while constructing the error message. The contract is never instantiated.

from abc import ABC, abstractmethod
from orionis.introspection import ReflectionAbstract
class Parent:
inherited = "base"
def inheritedMethod(self) -> str:
return "base"
class ReportContract(Parent, ABC):
"""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
@abstractmethod
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 = ReflectionAbstract(ReportContract)

Import from orionis.introspection; the direct orionis.introspection.abstract.reflection path is also available. Query methods are synchronous even when inspected members are async.

The scan traverses only Class.__dict__, not the MRO. Collection getters exclude inherited members; use getBaseClasses() to visit bases explicitly. A field created as self.field is not class data, and an annotation without a value is absent from attributes.

Classification distinguishes data, property, staticmethod, classmethod and other callables. It does not require every callable to be a conventional instance function. Async detection uses inspect.iscoroutinefunction() without execution: an async generator or a synchronous function returning an awaitable is not automatically classified as a coroutine function.

Public names do not start with _; protected names use _; private names are recognized through the class mangling prefix and exposed as __name. Dunder names also end in __ and are queried separately. Normalization follows the prefix Python generates after removing leading underscores from the class name.

Use private names as written in source ("__sign"), rather than "_ReportContract__sign". Classification compares prefixes; it is not access control and does not prevent private member access.

getClass

getClass(self) -> type

Returns the original class object (type) without constructing it.

assert r.getClass() is ReportContract

getClassName

getClassName(self) -> str

Returns the __name__ captured when constructing the wrapper as str, rather than __qualname__. clearCache() does not capture it again.

assert r.getClassName() == "ReportContract"

getModuleName

getModuleName(self) -> str

Returns the module name captured when constructing the wrapper as str. clearCache() does not capture it again.

assert r.getModuleName() == ReportContract.__module__

getModuleWithClassName

getModuleWithClassName(self) -> str

Returns module.ClassName as str, using names captured when constructing the wrapper. It does not add the enclosing scopes of a nested class.

assert r.getModuleWithClassName() == f"{ReportContract.__module__}.ReportContract"

getDocstring

getDocstring(self) -> str | None

Returns __doc__ or None; it neither cleans the text nor inherits another class docstring.

assert r.getDocstring() == "Report endpoint metadata."

getBaseClasses

getBaseClasses(self) -> list[type]

Returns a list of direct base classes (type); it does not traverse the complete MRO.

assert Parent in r.getBaseClasses()

getSourceCode

getSourceCode(self) -> str

Accepts no arguments. Returns the complete class source as str using inspect.getsource(). Converts OSError and TypeError to ValueError when unavailable. It does not accept a method selector.

assert "class ReportContract" in r.getSourceCode()

getFile

getFile(self) -> str

Returns the class file path as str. It converts a TypeError from inspect.getfile() into ValueError; it does not guarantee the file still exists.

assert r.getFile().endswith(".py")

getAnnotations

getAnnotations(self) -> dict

Returns a dict of class annotations, including fields annotated without a value. It removes the class prefix from private names and does not inspect method annotations.

assert "declared_only" in r.getAnnotations()
assert "__token" in r.getAnnotations()

hasAttribute

hasAttribute(self, attribute: str) -> bool

attribute is the required name of a class data attribute. Returns bool; methods, properties, inherited members and values only created by the constructor are excluded.

assert r.hasAttribute("format")
assert not r.hasAttribute("declared_only")
assert not r.hasAttribute("inherited")
assert not r.hasAttribute("instance_only")

getAttribute

getAttribute(self, attribute: str) -> object | None

Required attribute is looked up only in classified data. Returns its value or None if missing. No default argument is supported. Use hasAttribute() to distinguish a stored None from missing data.

assert r.getAttribute("format") == "json"
assert r.getAttribute("missing") is None
assert r.getAttribute("inherited") is None

getAttributes

getAttributes(self) -> dict

Returns a dict combining public, protected, normalized private and non-excluded dunder data, in that order. Instance fields and annotations without a value are excluded.

attributes = r.getAttributes()
assert attributes["format"] == "json"
assert attributes["__token"] == "secret"

getPublicAttributes

getPublicAttributes(self) -> dict

Returns a dict of data whose names do not begin with _.

assert r.getPublicAttributes()["format"] == "json"

getProtectedAttributes

getProtectedAttributes(self) -> dict

Returns a dict of data starting with _ that are neither private nor dunder.

assert r.getProtectedAttributes()["_label"] == "reports"

getPrivateAttributes

getPrivateAttributes(self) -> dict

Returns a dict of private data. Keys retain __ while omitting the class prefix introduced by Python.

assert r.getPrivateAttributes()["__token"] == "secret"

getDunderAttributes

getDunderAttributes(self) -> dict

Returns a dict of custom __name__ data. The implementation excludes Python metadata such as __dict__, __module__, __doc__ and __annotations__.

assert r.getDunderAttributes()["__feature__"] == "reports"
assert "__module__" not in r.getDunderAttributes()

getMagicAttributes

getMagicAttributes(self) -> dict

Alias of getDunderAttributes(); returns the same cached dictionary.

assert r.getMagicAttributes() is r.getDunderAttributes()

setAttribute

setAttribute(self, name: str, value: object) -> bool

name must be a valid Python identifier that is not a keyword (otherwise ValueError). Required value must not be callable (TypeError). Mutates the original class and returns True; private __names are supported. It neither validates annotations nor updates __abstractmethods__.

assert r.setAttribute("extra_label", "export") is True
assert ReportContract.extra_label == "export"
assert r.removeAttribute("extra_label") is True

removeAttribute

removeAttribute(self, name: str) -> bool

name identifies an own data attribute, using its original name when private. Removes the actual attribute and returns True. Raises ValueError when absent from the data classification; metaclass restrictions may propagate.

r.setAttribute("__temporary", 20)
assert r.removeAttribute("__temporary") is True
assert not r.hasAttribute("__temporary")

Although the callable error from setAttribute() mentions setMethod, ReflectionAbstract does not implement setMethod(). This wrapper provides no method for adding functions.

getMethods

getMethods(self) -> list[str]

Returns list[str]: instance, class and static methods, each category ordered by public, protected and private visibility. Properties and dunder methods are excluded; names are not alphabetically sorted.

methods = r.getMethods()
assert "render" in methods and "build" in methods and "normalize" in methods
assert "title" not in methods and "__repr__" not in methods

getPublicMethods

getPublicMethods(self) -> list[str]

Returns list[str] of public instance methods, including synchronous and asynchronous functions. It does not execute methods. No arguments are accepted.

assert "summary" in r.getPublicMethods()

getPublicSyncMethods

getPublicSyncMethods(self) -> list[str]

Returns list[str] of public instance methods that are not coroutine functions. It does not execute methods. No arguments are accepted.

assert "summary" in r.getPublicSyncMethods()
assert "fetch" not in r.getPublicSyncMethods()

getPublicAsyncMethods

getPublicAsyncMethods(self) -> list[str]

Returns list[str] of public instance methods recognized by inspect.iscoroutinefunction(). It does not execute methods. No arguments are accepted.

assert "fetch" in r.getPublicAsyncMethods()
assert "summary" not in r.getPublicAsyncMethods()

getProtectedMethods

getProtectedMethods(self) -> list[str]

Returns list[str] of protected instance methods, including synchronous and asynchronous functions. It does not execute methods. No arguments are accepted.

assert "_check" in r.getProtectedMethods()

getProtectedSyncMethods

getProtectedSyncMethods(self) -> list[str]

Returns list[str] of protected instance methods that are not coroutine functions. It does not execute methods. No arguments are accepted.

assert "_check" in r.getProtectedSyncMethods()
assert "_fetch" not in r.getProtectedSyncMethods()

getProtectedAsyncMethods

getProtectedAsyncMethods(self) -> list[str]

Returns list[str] of protected instance methods recognized by inspect.iscoroutinefunction(). It does not execute methods. No arguments are accepted.

assert "_fetch" in r.getProtectedAsyncMethods()
assert "_check" not in r.getProtectedAsyncMethods()

getPrivateMethods

getPrivateMethods(self) -> list[str]

Returns list[str] of private instance methods, including synchronous and asynchronous functions. Results use __name, without the class prefix. It does not execute methods. No arguments are accepted.

assert "__sign" in r.getPrivateMethods()

getPrivateSyncMethods

getPrivateSyncMethods(self) -> list[str]

Returns list[str] of private instance methods that are not coroutine functions. Results use __name, without the class prefix. It does not execute methods. No arguments are accepted.

assert "__sign" in r.getPrivateSyncMethods()
assert "__fetch" not in r.getPrivateSyncMethods()

getPrivateAsyncMethods

getPrivateAsyncMethods(self) -> list[str]

Returns list[str] of private instance methods recognized by inspect.iscoroutinefunction(). Results use __name, without the class prefix. It does not execute methods. No arguments are accepted.

assert "__fetch" in r.getPrivateAsyncMethods()
assert "__sign" not in r.getPrivateAsyncMethods()

getPublicClassMethods

getPublicClassMethods(self) -> list[str]

Returns list[str] of public class (@classmethod) methods, including synchronous and asynchronous functions. It does not execute methods. No arguments are accepted.

assert "build" in r.getPublicClassMethods()

getPublicClassSyncMethods

getPublicClassSyncMethods(self) -> list[str]

Returns list[str] of public class (@classmethod) methods that are not coroutine functions. It does not execute methods. No arguments are accepted.

assert "build" in r.getPublicClassSyncMethods()
assert "buildAsync" not in r.getPublicClassSyncMethods()

getPublicClassAsyncMethods

getPublicClassAsyncMethods(self) -> list[str]

Returns list[str] of public class (@classmethod) methods recognized by inspect.iscoroutinefunction(). It does not execute methods. No arguments are accepted.

assert "buildAsync" in r.getPublicClassAsyncMethods()
assert "build" not in r.getPublicClassAsyncMethods()

getProtectedClassMethods

getProtectedClassMethods(self) -> list[str]

Returns list[str] of protected class (@classmethod) methods, including synchronous and asynchronous functions. It does not execute methods. No arguments are accepted.

assert "_build" in r.getProtectedClassMethods()

getProtectedClassSyncMethods

getProtectedClassSyncMethods(self) -> list[str]

Returns list[str] of protected class (@classmethod) methods that are not coroutine functions. It does not execute methods. No arguments are accepted.

assert "_build" in r.getProtectedClassSyncMethods()
assert "_buildAsync" not in r.getProtectedClassSyncMethods()

getProtectedClassAsyncMethods

getProtectedClassAsyncMethods(self) -> list[str]

Returns list[str] of protected class (@classmethod) methods recognized by inspect.iscoroutinefunction(). It does not execute methods. No arguments are accepted.

assert "_buildAsync" in r.getProtectedClassAsyncMethods()
assert "_build" not in r.getProtectedClassAsyncMethods()

getPrivateClassMethods

getPrivateClassMethods(self) -> list[str]

Returns list[str] of private class (@classmethod) methods, including synchronous and asynchronous functions. Results use __name, without the class prefix. It does not execute methods. No arguments are accepted.

assert "__build" in r.getPrivateClassMethods()

getPrivateClassSyncMethods

getPrivateClassSyncMethods(self) -> list[str]

Returns list[str] of private class (@classmethod) methods that are not coroutine functions. Results use __name, without the class prefix. It does not execute methods. No arguments are accepted.

assert "__build" in r.getPrivateClassSyncMethods()
assert "__buildAsync" not in r.getPrivateClassSyncMethods()

getPrivateClassAsyncMethods

getPrivateClassAsyncMethods(self) -> list[str]

Returns list[str] of private class (@classmethod) methods recognized by inspect.iscoroutinefunction(). Results use __name, without the class prefix. It does not execute methods. No arguments are accepted.

assert "__buildAsync" in r.getPrivateClassAsyncMethods()
assert "__build" not in r.getPrivateClassAsyncMethods()

getPublicStaticMethods

getPublicStaticMethods(self) -> list[str]

Returns list[str] of public static (@staticmethod) methods, including synchronous and asynchronous functions. It does not execute methods. No arguments are accepted.

assert "normalize" in r.getPublicStaticMethods()

getPublicStaticSyncMethods

getPublicStaticSyncMethods(self) -> list[str]

Returns list[str] of public static (@staticmethod) methods that are not coroutine functions. It does not execute methods. No arguments are accepted.

assert "normalize" in r.getPublicStaticSyncMethods()
assert "normalizeAsync" not in r.getPublicStaticSyncMethods()

getPublicStaticAsyncMethods

getPublicStaticAsyncMethods(self) -> list[str]

Returns list[str] of public static (@staticmethod) methods recognized by inspect.iscoroutinefunction(). It does not execute methods. No arguments are accepted.

assert "normalizeAsync" in r.getPublicStaticAsyncMethods()
assert "normalize" not in r.getPublicStaticAsyncMethods()

getProtectedStaticMethods

getProtectedStaticMethods(self) -> list[str]

Returns list[str] of protected static (@staticmethod) methods, including synchronous and asynchronous functions. It does not execute methods. No arguments are accepted.

assert "_normalize" in r.getProtectedStaticMethods()

getProtectedStaticSyncMethods

getProtectedStaticSyncMethods(self) -> list[str]

Returns list[str] of protected static (@staticmethod) methods that are not coroutine functions. It does not execute methods. No arguments are accepted.

assert "_normalize" in r.getProtectedStaticSyncMethods()
assert "_normalizeAsync" not in r.getProtectedStaticSyncMethods()

getProtectedStaticAsyncMethods

getProtectedStaticAsyncMethods(self) -> list[str]

Returns list[str] of protected static (@staticmethod) methods recognized by inspect.iscoroutinefunction(). It does not execute methods. No arguments are accepted.

assert "_normalizeAsync" in r.getProtectedStaticAsyncMethods()
assert "_normalize" not in r.getProtectedStaticAsyncMethods()

getPrivateStaticMethods

getPrivateStaticMethods(self) -> list[str]

Returns list[str] of private static (@staticmethod) methods, including synchronous and asynchronous functions. Results use __name, without the class prefix. It does not execute methods. No arguments are accepted.

assert "__normalize" in r.getPrivateStaticMethods()

getPrivateStaticSyncMethods

getPrivateStaticSyncMethods(self) -> list[str]

Returns list[str] of private static (@staticmethod) methods that are not coroutine functions. Results use __name, without the class prefix. It does not execute methods. No arguments are accepted.

assert "__normalize" in r.getPrivateStaticSyncMethods()
assert "__normalizeAsync" not in r.getPrivateStaticSyncMethods()

getPrivateStaticAsyncMethods

getPrivateStaticAsyncMethods(self) -> list[str]

Returns list[str] of private static (@staticmethod) methods recognized by inspect.iscoroutinefunction(). Results use __name, without the class prefix. It does not execute methods. No arguments are accepted.

assert "__normalizeAsync" in r.getPrivateStaticAsyncMethods()
assert "__normalize" not in r.getPrivateStaticAsyncMethods()

hasMethod

hasMethod(self, name: str) -> bool

Required name is checked against own instance, class and static methods. Returns bool; private names use their unmangled spelling. Dunder methods are separate and return False here.

assert r.hasMethod("render")
assert r.hasMethod("__sign")
assert not r.hasMethod("__repr__")
assert not r.hasMethod("inheritedMethod")

removeMethod

removeMethod(self, name: str) -> bool

Removes own method name from the class and returns True; raises ValueError when hasMethod() is false. Private names and static/class descriptors are supported. It cannot remove dunder or inherited methods.

original_summary = ReportContract.__dict__["summary"]
assert r.removeMethod("summary") is True
assert not r.hasMethod("summary")
setattr(ReportContract, "summary", original_summary)
r.clearCache()

getDunderMethods

getDunderMethods(self) -> list[str]

Returns list[str] of own __name__ callables that are not properties, staticmethods or classmethods. Includes __init__ when defined on the class.

assert "__repr__" in r.getDunderMethods()
assert "__init__" in r.getDunderMethods()

getMagicMethods

getMagicMethods(self) -> list[str]

Alias of getDunderMethods(); returns the same cached list.

assert r.getMagicMethods() is r.getDunderMethods()

getProperties

getProperties(self) -> list[str]

Returns list[str] of own property descriptors. It preserves declaration order, normalizes private names and does not execute getters.

assert r.getProperties() == ["title", "_title", "__title"]

getPublicProperties

getPublicProperties(self) -> list[str]

Returns list[str] of public properties.

assert r.getPublicProperties() == ["title"]

getProtectedProperties

getProtectedProperties(self) -> list[str]

Returns list[str] of protected properties.

assert r.getProtectedProperties() == ["_title"]

getPrivateProperties

getPrivateProperties(self) -> list[str]

Returns list[str] of private properties using their original spelling.

assert r.getPrivateProperties() == ["__title"]

getPropertySignature

getPropertySignature(self, name: str) -> inspect.Signature

Required name returns inspect.Signature for the fget getter, including self, without executing it. Supports private and inherited properties accessible through getattr(). Raises ValueError when missing, and TypeError for non-properties or uninspectable getters.

assert list(r.getPropertySignature("title").parameters) == ["self"]
assert list(r.getPropertySignature("__title").parameters) == ["self"]

getPropertyDocstring

getPropertyDocstring(self, name: str) -> str | None

Required name returns str | None containing the fget docstring; a missing getter yields None. Supports private and inherited properties. Raises ValueError when absent and TypeError when the attribute is not a property.

assert r.getPropertyDocstring("title") == "Report title."
assert r.getPropertyDocstring("__title") == "Report title."

getMethodSignature

getMethodSignature(self, name: str) -> inspect.Signature

Required name returns inspect.Signature without invoking the method: instance signatures retain self, whereas bound classmethods omit cls. Raises ValueError if not classified and TypeError if no longer callable; inspection errors can also propagate.

signature = r.getMethodSignature("render")
assert list(signature.parameters) == ["self", "item_id", "mode"]
assert "cls" not in r.getMethodSignature("build").parameters
assert "self" not in r.getMethodSignature("normalize").parameters

constructorSignature

constructorSignature(self) -> Signature

Returns the Orionis Signature describing __init__ dependencies without constructing the class. Its resolved, unresolved and ordered maps contain Argument objects. This is neither inspect.Signature nor service instance resolution.

analysis = r.constructorSignature()
assert list(analysis.ordered) == ["limit"]
assert analysis.resolved["limit"].default == 10

methodSignature

methodSignature(self, method_name: str) -> Signature

Required method_name returns a dependency Signature for an own method, omitting self/cls and classifying arguments without execution. Raises AttributeError when hasMethod() is false; analyzer errors propagate. Private names are supported.

analysis = r.methodSignature("render")
assert list(analysis.ordered) == ["item_id", "mode"]
assert "item_id" in analysis.unresolved
assert analysis.resolved["mode"].default == "brief"

The last two methods delegate to ReflectDependencies. resolved means sufficient type or default-value metadata exists; it does not mean a service has been created or registered. Required built-in item_id: int remains unresolved, whereas mode="brief" has a known default.

The first member getter performs the scan. Returned lists and dictionaries are the cached objects rather than defensive copies. Do not modify them to “edit” the class: that alters the cached view and may make queries inconsistent. Use mutation methods or copy returned results.

setAttribute(), removeAttribute() and removeMethod() invalidate member classifications but can retain previously computed signatures and other results. Call clearCache() after changing signatures, annotations or metadata. Direct changes to the class are not detected automatically either.

The class name, module name and private prefix are captured during construction and do not change after clearCache(). Construct another wrapper after changing __name__ or __module__. The docstring is read directly on each call.

The following operators access the wrapper cache, rather than class attributes. Use custom keys distinct from internal keys (attributes, methods, etc.); overwriting or deleting internal keys can break scan consistency.

__setitem__

__setitem__(self, key: str, value: object) -> None

Stores required value under required key; returns None. It does not change the class.

r["app:note"] = "reviewed"
assert r["app:note"] == "reviewed"

__getitem__

__getitem__(self, key: str) -> object | None

Returns the value under required key, or None when absent; it does not raise KeyError. Use in to distinguish a key storing None.

assert r["app:note"] == "reviewed"
assert r["app:absent"] is None

__contains__

__contains__(self, key: str) -> bool

Returns bool indicating whether required key is stored, including when its value is None.

r["app:empty"] = None
assert "app:empty" in r
assert "app:absent" not in r

__delitem__

__delitem__(self, key: str) -> None

Removes required key, returns None and ignores missing keys.

del r["app:note"]
del r["app:absent"]
assert "app:note" not in r

clearCache

clearCache(self) -> None

Returns None. Discards all data cached in this wrapper, including custom bracket keys. The next query recomputes reflection; this neither reverses class mutations nor empties the global dependency cache.

r["app:note"] = "cached"
assert r.clearCache() is None
assert "app:note" not in r
assert "render" in r.getPublicMethods()

The wrapper must know which class to inspect. Annotating a parameter as ReflectionAbstract does not automatically select your application contract or component. Construct the reflector when the target is known, or encapsulate it in your own resolvable service. No native binding chooses that target for you.

from orionis.http import JSONResponse
class ReportCatalog:
def __init__(self) -> None:
self.reflection = ReflectionAbstract(ReportContract)
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()})

Here, ReportCatalog is an application service with a no-argument constructor. The catalog explicitly creates the reflector and returns a list copy. Constructor injection into another service uses the same catalog: ReportCatalog annotation. Direct access remains valid outside controllers. See the container for registrations, lifetimes and custom contracts.

Queries do not execute actions or turn annotations into data validation. Mutations are real and affect every consumer of the class in the process; no class copy is created, and deleting the reflector does not undo changes. Descriptor or metaclass restrictions can make an operation fail; those exceptions propagate.

Method getters do not separate abstract declarations from concrete implementations: both appear according to visibility and descriptor type. The wrapper does not call abc.update_abstractmethods() after a mutation.

A name returned by getDunderMethods() is not automatically valid for hasMethod(), removeMethod(), getMethodSignature() or methodSignature(): these operations use the non-dunder method list. Properties have their own APIs.

Clearing this wrapper does not empty the shared ReflectDependencies caches after dynamic function changes. New functions are analyzed by identity, whereas editing annotations or defaults on the same function can leave earlier analysis cached; see the dependency guide.